简体   繁体   English

如何从 Spring Security 中注销当前用户?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM