【问题标题】:Custom Success Handler in spring bootSpring Boot 中的自定义成功处理程序
【发布时间】:2018-08-20 08:43:40
【问题描述】:

我按照教程 https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/ 将 jwt 集成到我的应用程序中。我正在尝试向我的应用程序添加自定义成功处理程序。不幸的是,成功的处理程序不会在成功的登录请求时触发。我正在尝试返回一个用户对象,而不是标头中带有令牌的空响应。我的处理程序是

@Component
public class AuthSuccessHandler implements AuthenticationSuccessHandler {
    @Autowired
    private ApplicationUserRepository userRepository;
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        UserDetails user = (UserDetails) authentication.getPrincipal();
        AuthInfo authInfo = new AuthInfo();
        authInfo.setUser(userRepository.findOneByUserName(user.getUsername()));
        authInfo.setToken(response.getHeader("Authentication"));
        response.getWriter().write(objectMapper.writeValueAsString(authInfo));
        response.setContentType("application/json");
        response.setStatus(200);
    }

}

我已经在WebSecurityConfigurer.configure()中配置为

protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
            .antMatchers(HttpMethod.GET, "/public/**").permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .successHandler(successHandler)
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager(), securityConfig))
            .addFilter(new JWTAuthorizationFilter(authenticationManager(), securityConfig))
            // this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

@pvpkiran 的解决方案不起作用。在调试时,我发现 authenticationfilter 运行了两次并且授权过滤器没有触发。下面给出了应用程序日志中可用的过滤器列表

Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  CorsFilter
  LogoutFilter
  JWTAuthenticationFilter
  JWTAuthorizationFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

【问题讨论】:

    标签: java spring-boot spring-security jwt


    【解决方案1】:

    试试这个。像这样创建一个本地方法。

     public JwtAuthenticationTokenFilter authenticationTokenFilter() {
            JwtAuthenticationTokenFilter filter = new JwtAuthenticationTokenFilter();
            filter.setAuthenticationManager(authenticationManager());
            filter.setAuthenticationSuccessHandler(successHandler);
            return filter;
        }
    

    然后像这样改变你的配置方法

    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
                .antMatchers(HttpMethod.GET, "/public/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
                http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    

    另一点是最好不要让你的AuthSuccessHandler 成为一个bean(删除@Component)并在你的安全配置中创建一个这样的AuthSucessHandler 对象。原因是,如果您将 AuthSuccessHandler 声明为 bean,spring 将扫描它并添加两个 SuccessHandlers(
    1.当它扫描bean时,
    2. 在您的 SecurityConfig 中添加它时。
    )

    @EnableWebSecurity
    @Configuration
    public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private ApplicationUserRepository userRepository;
        @Autowired
        private ObjectMapper objectMapper;
    
        public JwtAuthenticationTokenFilter authenticationTokenFilter() {
            JwtAuthenticationTokenFilter filter = new JwtAuthenticationTokenFilter();
            filter.setAuthenticationManager(authenticationManager());
            AuthSuccessHandler successHandler = new AuthSuccessHandler(userRepository, objectMapper):
            filter.setAuthenticationSuccessHandler(successHandler);
            return filter;
        }
    
    
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
                .antMatchers(HttpMethod.GET, "/public/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
                http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    }
    

    像这样改变你的 AuthSuccessHandler

    public class AuthSuccessHandler implements AuthenticationSuccessHandler {
        private ApplicationUserRepository userRepository;
        private ObjectMapper objectMapper;
    
        public AuthSuccessHandler(ApplicationUserRepository userRepository, ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
            this.userRepository = userRepository;
        }
    
        ........
     }   
    

    【讨论】:

    • 这不起作用。看来我的配置有问题。我会更新问题。
    • 这取决于您的测试方式
    • 是什么意思?我正在使用 http post 到 url '/login' 进行身份验证。看起来 authenticationFilter 正在进行两次身份验证,并且没有触发授权。下面给出的是日志安全过滤器链中的过滤器链: [ WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter CorsFilter LogoutFilter JWTAuthenticationFilter JWTAuthorizationFilter RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter AnonymousAuthenticationFilter SessionManagementFilter ExceptionTranslationFilter FilterSecurityInterceptor ]
    • 我解释了为什么会发生两次
    • JWTAuthenticationFilter 不是一个组件。当我从配置中删除它时,它不会触发。
    猜你喜欢
    • 2023-03-04
    • 2019-04-11
    • 1970-01-01
    • 2022-10-19
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 2011-09-26
    相关资源
    最近更新 更多