web-dev-qa-db-ja.com

Spring Securityのデフォルトのログインと認証を使用してユーザーをHttpSessionに配置します

私は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 UserDetailsS​​erviceImplクラス:

@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
    }

}
4
John Student

ログインに成功したときにセッションにユーザーを追加したい場合は、以下のようにAuthenticationSuccessHandlerを作成し、successHandler(new AuthenticationSuccessHandlerImpl())を使用して登録できます。

更新:オブジェクトAuthenticationSuccessHandlerImplを作成した場合、それはスプリング管理されないため、autowireSecurityconfigに入れて、以下に示すように使用します。

ここで、AuthenticationSuccessHandlerWebSecurityConfigを自動配線します

@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);

    }

}

お役に立てれば。

8