[英]How to logout current user from Spring Security?
I have a simple Springboot server using Spring Security and I am having trouble logging the user out.我有一个使用 Spring Security 的简单 Springboot 服务器,但我无法将用户注销。
Expected outcome: I expected to be able to hit the endpoint /logout
in my browser's URL and then I would be asked to log in again.预期结果:我希望能够在浏览器的 URL 中点击端点/logout
,然后我会被要求再次登录。
Actual outcome: I hit the /logout
endpoint, and the user is still logged in. I can still see all routes that should be hidden to users that are not logged in.实际结果:我点击了/logout
端点,用户仍然登录。我仍然可以看到所有应该对未登录用户隐藏的路由。
This is my SpringConfiguration.java
file:这是我的SpringConfiguration.java
文件:
@Configuration
@EnableConfigurationProperties
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
MongoUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/register").permitAll().anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().disable();
http.logout().clearAuthentication(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/logout.done").invalidateHttpSession(true);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
}
After I naviagte to /logout
in my browser, the url changes to logout.done
but I can still see pages that I should not have access to.在我的浏览器中导航到/logout
后,url 更改为logout.done
但我仍然可以看到我不应该访问的页面。
I have also tried this with the same results:我也试过这个,结果相同:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/register").permitAll().anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().disable().logout()
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true)
.and().csrf().disable();
}
And the CustomLogoutSuccessHandler.java
looks like this: CustomLogoutSuccessHandler.java
看起来像这样:
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
Cookie cookie = new Cookie("JSESSIONID", null);
cookie.setPath(request.getContextPath());
cookie.setMaxAge(0);
response.addCookie(cookie);
if (request.getParameter("expired") != null) {
response.sendRedirect(request.getContextPath() + "/login?expired=true");
} else {
response.sendRedirect(request.getContextPath() + "/login?logout=true");
}
}
}
I also tried this configuration, and still, the same result...我也试过这个配置,结果还是一样...
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/register").permitAll().anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().disable();
http.csrf().disable()
.logout(logout -> logout
.clearAuthentication(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID"));
}
Trying what Ajay mentioned has also failed me.尝试 Ajay 提到的内容也让我失望了。 My config now looks like this:我的配置现在看起来像这样:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/register").permitAll().anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().disable();
// TODO : LOGOUT IS NOT WORKING
http.csrf().disable()
.logout(logout -> logout
.permitAll()
.clearAuthentication(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID"));
}
Controller: Controller:
public String logoutPage(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
SecurityContextHolder.getContext().setAuthentication(null);
logger.info("logged out");
}
return "redirect:login?logout";
}
Not sure what you have on logout.done page.不确定您在 logout.done 页面上有什么。 But this is how I would logout.但这就是我注销的方式。
Suggestion: Your logoutSuccessUrl
should be either your home page or you might want to redirect user back to login page.建议:您的logoutSuccessUrl
应该是您的主页,或者您可能希望将用户重定向回登录页面。
Controller : To nullify the authentication and to redirect to some page (say - login page). Controller :使身份验证无效并重定向到某个页面(比如登录页面)。
@RequestMapping(value = "logout", method = RequestMethod.GET)
public String logoutPage(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
SecurityContextHolder.getContext().setAuthentication(null);
}
return "redirect:login?logout";
}
My Config :我的配置:
(...).formLogin().loginPage("/login").permitAll().and().logout().permitAll().and().(...)
And View (say jsp) :和查看(比如jsp) :
<a href="${contextPath}/logout">Logout</a>
Not just this, there are other (similar) ways to do it too.不仅如此,还有其他(类似的)方法可以做到这一点。 Also you will find numerous example over the web and lots of SO threads too for the similar situation.您还会在 web 上找到许多示例,并且对于类似情况也有很多 SO 线程。 I would recommend take a look what different approaches people are following to achieve this.我建议看看人们正在遵循哪些不同的方法来实现这一目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.