我知道,有很多关于这个主题的文章,但我有一个问题,我找不到任何解决方案。
我有一个经典的 spring security java 配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuctionAuthenticationProvider auctionAuthenticationProvider;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(auctionAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequest = http.authorizeRequests();
configureAdminPanelAccess(authorizeRequest);
configureFrontApplicationAccess(authorizeRequest);
configureCommonAccess(authorizeRequest);
http.csrf()
.csrfTokenRepository(csrfTokenRepository()).and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
http.logout()
.clearAuthentication(true)
.invalidateHttpSession(true);
}
...
}
另外,我有两个控制器方法,我通过 AJAX 从我的 Web 应用程序登录/注销。
当我想注销时,我首先调用这个方法,我希望它能清除用户会话并清除安全上下文中的所有内容。
@Override
@RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<Boolean> logout(final HttpServletRequest request, final HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK);
}
在此之后,我重新加载我的客户端 Web 应用程序,每次重新加载时,我都会通过调用以下控制器方法检查用户是否已通过身份验证:
@Override
@RequestMapping(value = "/user", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<UserDetails> user() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
return new ResponseEntity<>((UserDetails) principal, HttpStatus.OK);
}
return null;
}
在这里我收到了最后一个经过身份验证的用户。貌似前面的logout方法,Spring logout是不行的。
请记住,我尝试使用以下代码注销,但没有成功:
@Override
@RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<Boolean> logout(final HttpServletRequest request) {
try {
request.logout();
return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK);
} catch (ServletException ex) {
if (LOG.isDebugEnabled()) {
LOG.debug("There is a problem with the logout of the user", ex);
}
}
您知道我在配置和注销过程中遗漏了什么吗?
原文由 Streetsouls 发布,翻译遵循 CC BY-SA 4.0 许可协议
根据您的问题,我看到您正在尝试创建自己的注销并且您还尝试使用默认的 Spring 注销。我建议您应该选择一种方法,不要将它们混合使用。我建议从 Spring 注销两个:
第一:默认spring security注销
从上面的示例中,只要您想注销用户,您只需要调用
/logout
URL。无需创建任何@Controller
来处理注销,Spring 将帮助注销用户。您还可以在此处添加其他要使其无效的内容。第二:以编程方式注销
如果您使用这种注销方法,则不需要在 ht eSpring 安全配置中包含第一种方法。通过使用此方法,您可以在注销完成之前和之后添加要执行的额外操作。顺便说一句,要使用此注销,只需调用
/logout
url,用户将被手动注销。此方法将使会话无效,清除 Spring 安全上下文和 cookie。除了第二种方法,如果您使用的是
RequestMethod.POST
,则需要在 POST 请求中包含 CSRF 密钥。另一种方法是创建一个带有隐藏输入 CSRF 密钥的表单。这是使用 jQuery 自动生成的注销链接的一些示例:您只需要创建一个超链接
<a id="Logout">Logout</a>
即可使用它。如果您使用的是
RequestMethod.GET
,只需在您的链接中包含一个 CSRF 密钥作为参数,如下所示:仅此而已,希望对您有所帮助。