私はJava Developperの1年生のフランス人学生です。
Spring Boot、Spring security、Hibernate、Spring Data、Spring MVC、Thymeleafを使用して小さなマルチモジュールアプリを開発しています。
ログイン時に、セッションでユーザー、または少なくともuserIdを設定したいと思います。このようにして、必要になるたびにセッションやモデルに手動で配置する必要はありません。
しかし、デフォルトのSpring Securityのログインと認証の構成を使用しているので、そのようなメソッドを呼び出す方法と場所が本当にわかりません。
void putUserInHttpSession( HttpSession httpSession ) {
httpSession.setAttribute( "user" , getManagerFactory().getUserManager().findByUserName( SecurityContextHolder.getContext().getAuthentication().getName()) );
}
必要なときにすぐに実行できますが、ログイン時にこれを実行しないのはかなり醜いです。
これが私を助ける必要があると私が思うものです(それは素晴らしいでしょう!!! :)
My WebSecurityConfigクラス:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login").defaultSuccessUrl("/public/showAtlas")//
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
My UserDetailsServiceImplクラス:
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private ManagerFactory managerFactory;
// private HttpSession httpSession;
/**
* The authentication method uses the user email, since it is easier to remember for most users
* @param input
* @return a UserDetails object
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername( String input) throws UsernameNotFoundException {
User user = new User();
if( input.contains( "@" )){
user = this.managerFactory.getUserManager().findByEmail( input );
}
else {
user = this.managerFactory.getUserManager().findByUserName( input );
}
if (user == null) {
throw new UsernameNotFoundException( "User with email " + input + " was not found in the database" );
}
// [ROLE_USER, ROLE_ADMIN,..]
List<String> roleNames = this.managerFactory.getRoleManager().findRoleByUserName(user.getUserName());
List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();
if (roleNames != null) {
for (String role : roleNames) {
// ROLE_USER, ROLE_ADMIN,..
GrantedAuthority authority = new SimpleGrantedAuthority(role);
grantList.add(authority);
}
}
return (UserDetails) new org.springframework.security.core.userdetails.User(user.getUserName(),
user.getPassword(), grantList);
}
}
私の単純なLoginController:
@Controller
public class LoginController{
@GetMapping("/public/login")
public String login(Model model ){
return "view/login";
}
@GetMapping("/public/logoutSuccessful")
public String logout(Model model) {
return "view/logoutSuccessful";
}
それで、ログイン時にユーザーまたはuserIdをhttpSessionに入れる簡単な方法はありますか?
ありがとうございました!!!
ソリューション
CustomAuthenticationSuccessHandlerを作成します
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private ManagerFactory managerFactory;
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
String userName = "";
HttpSession session = request.getSession();
Collection< GrantedAuthority > authorities = null;
if(authentication.getPrincipal() instanceof Principal ) {
userName = ((Principal)authentication.getPrincipal()).getName();
session.setAttribute("role", "none");
}else {
User userSpringSecu = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("role", String.valueOf( userSpringSecu.getAuthorities()));
session.setAttribute( "connectedUser" , managerFactory.getUserManager().findByUserName( userSpringSecu.getUsername() ) );
}
response.sendRedirect("/public/showAtlas" );
}
}
次に、このクラスを自動配線し、WebSecurityConfigurerAdapterに追加します
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// http.exceptionHandling().accessDeniedPage( "/error/403" );
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login")
.defaultSuccessUrl("/public/showAtlas")//
.successHandler( customAuthenticationSuccessHandler )
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
ログインに成功したときにセッションにユーザーを追加したい場合は、以下のようにAuthenticationSuccessHandler
を作成し、successHandler(new AuthenticationSuccessHandlerImpl())
を使用して登録できます。
更新:オブジェクトAuthenticationSuccessHandlerImpl
を作成した場合、それはスプリング管理されないため、autowire
をSecurityconfig
に入れて、以下に示すように使用します。
ここで、AuthenticationSuccessHandler
のWebSecurityConfig
を自動配線します
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
そしてそれを使用しますWebSecurityConfig.Java
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll().successHandler(authenticationSuccessHandler) // See here
.and()
.logout()
.permitAll();
}
AuthenticationSuccessHandlerImpl.Java
import Java.io.IOException;
import Java.security.Principal;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.techdisqus.auth.repository.UserRepository;
@Component
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler{
@Autowired HttpSession session; //autowiring session
@Autowired UserRepository repository; //autowire the user repo
private static final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessHandlerImpl.class);
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
// TODO Auto-generated method stub
String userName = "";
if(authentication.getPrincipal() instanceof Principal) {
userName = ((Principal)authentication.getPrincipal()).getName();
}else {
userName = ((User)authentication.getPrincipal()).getUsername();
}
logger.info("userName: " + userName);
//HttpSession session = request.getSession();
session.setAttribute("userId", userName);
}
}
お役に立てれば。