我面临一个有趣的问题。通过实施AuthenticationProvider
。
查看我的私有方法以获取安全上下文。当我使用SecurityContextHolder.getContext()
时,我得到的是没有身份验证的空上下文对象,但是当我从会话中读取它时,它似乎正常工作(session.getAttribute(“SPRING_SECURITY_CONTEXT”))
private SecurityContext getSecurityContext() throws ServiceException {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession(false);
SecurityContext context = SecurityContextHolder.getContext();
if (context == null || context.getAuthentication() == null) {
if (session == null) {
throw new ServiceException(ErrorCode.INVALID_REQUEST, "User has not logged in");
}
context = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
}
return context;// SecurityContextHolder.getContext();
当我调试代码时, SecurityContextPersistenceFilter 中的finally块被称为清空SecurityContextHolder。这导致创建并返回空的上下文对象(因此后续调用时身份验证令牌为空)。
finally {
SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
// Crucial removal of SecurityContextHolder contents - do this before anything else.
**SecurityContextHolder.clearContext();**
repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
request.removeAttribute(FILTER_APPLIED);
if (debug) {
logger.debug("SecurityContextHolder now cleared, as request processing completed");
}
看起来像SecurityContextPersistenceFilter
过滤器应该在认证后执行实际身份验证之前执行,从而导致此错误行为。
这也是我的配置
http
.exceptionHandling()
.accessDeniedHandler(getAccessDeniedHandler()).and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint).and()
.formLogin()
.failureUrl("/accessdenied").loginPage("/accessdenied").loginProcessingUrl("/login")
.successHandler(loginSuccessHandler).failureHandler(loginFailedHandler)
.usernameParameter("j_username").passwordParameter("j_password").and()
.logout()
.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler)
.deleteCookies("JSESSIONID").permitAll().and()
.antMatcher("/login")
.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.headers().frameOptions().disable()
.authorizeRequests()
.antMatchers("/logout").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/accessdenied").permitAll()
.antMatchers("/master/countries").permitAll()
.antMatchers("/master/languages").permitAll()
.antMatchers("/captcha**").permitAll()
.antMatchers("/page").permitAll()
.antMatchers("/common/**").permitAll()
.antMatchers("/member/registration").permitAll()
.antMatchers("/ewallet**").authenticated()
.antMatchers("/transfer**").authenticated()
.antMatchers("/sales**").authenticated()
.antMatchers("/products**").authenticated()
.antMatchers("/events").authenticated()
.antMatchers("/archives").authenticated()
.antMatchers("/announcements").authenticated();
这是对的吗?或者需要进行任何更改。我想我在这里错过了一些东西。我想在登录过滤器工作之前使用验证码过滤器。