前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Security---退出功能详解

Spring Security---退出功能详解

作者头像
大忽悠爱学习
发布2021-12-07 18:52:51
发布2021-12-07 18:52:51
2.3K00
代码可运行
举报
文章被收录于专栏:c++与qt学习c++与qt学习
运行总次数:0
代码可运行

Spring Security---退出功能详解


logout退出登录

其实使用Spring Security进行logout非常简单,只需要在spring Security配置类配置项上加上这样一行代码:http.logout()。关于spring Security配置类的其他很多实现、如:HttpBasic模式、formLogin模式、自定义登录验证结果、使用权限表达式、session会话管理,。本节的核心内容就是在原有配置的基础上,加上这样一行代码:http.logout()。

代码语言:javascript
代码运行次数:0
运行
复制
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.logout();
   }

}

加上logout配置之后,在你的“退出”按钮上使用/logout作为请求登出的路径。

代码语言:javascript
代码运行次数:0
运行
复制
<a href="/logout" >退出</a>

默认的logout做了什么?

虽然我们简简单单的实现了logout功能,是不是还不足够放心?我们下面就来看一下Spring Security默认在logout过程中帮我们做了哪些动作。

  • 当前session失效,即:logout的核心需求,session失效就是访问权限的回收。
  • 删除当前用户的 remember-me“记住我”功能信息
  • clear清除当前的 SecurityContext
  • 重定向到登录页面,loginPage配置项指定的页面

通常对于一个应用来讲,以上动作就是logout功能所需要具备的功能了。


个性化配置

虽然Spring Security默认使用了/logout作为退出处理请求路径,登录页面作为退出之后的跳转页面。这符合绝大多数的应用的开发逻辑,但有的时候我们需要一些个性化设置,如下:

代码语言:javascript
代码运行次数:0
运行
复制
 http.logout()
     .logoutUrl("/signout")
     .logoutSuccessUrl("/aftersignout.html")
     .deleteCookies("JSESSIONID")
  • 通过指定logoutUrl配置改变退出请求的默认路径,当然html退出按钮的请求url也要修改
  • 通过指定logoutSuccessUrl配置,来显式指定退出之后的跳转页面
  • 还可以使用deleteCookies删除指定的cookie,参数为cookie的名称

演示

配置类:

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   private ObjectMapper objectMapper=new ObjectMapper();

   @Bean
   PasswordEncoder passwordEncoder() {
      return NoOpPasswordEncoder.getInstance();
   }

   @Override
   public void configure(WebSecurity web) throws Exception {
      web.ignoring().antMatchers("/js/**", "/css/**","/images/**");
   }

   //数据源注入
   @Autowired
   DataSource dataSource;

   //持久化令牌配置
   @Bean
   JdbcTokenRepositoryImpl jdbcTokenRepository() {
      JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
      jdbcTokenRepository.setDataSource(dataSource);
      return jdbcTokenRepository;
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
              .antMatchers("/admin/**").hasRole("admin")
              .antMatchers("/user/**").hasRole("user")
              .anyRequest().authenticated()
              .and()
              .formLogin()
              .loginPage("/login.html").permitAll()
              .loginProcessingUrl("/login").permitAll()
              .defaultSuccessUrl("/main.html")//可以记住上一次的请求路径
              .failureHandler(new AuthenticationFailureHandler() {
                 @Override
                 public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                    httpServletResponse.setContentType("text/html;charset=utf-8");
                    httpServletResponse.getWriter().write("登录失败");
                 }
              })
              .and()
              .logout()
              //退出登录的请求,是再没退出前发出的,因此此时还有登录凭证
              //可以访问
              .logoutUrl("/logout")
              //此时已经退出了登录,登录凭证没了
              //那么想要访问非登录页面的请求,就必须保证这个请求无需凭证即可访问
              .logoutSuccessUrl("/logout.html").permitAll()
              .deleteCookies("JSESSIONID")
              .and()
              .rememberMe()
              .key("dhy")
              .tokenRepository(jdbcTokenRepository())
              .and()
              .csrf().disable();

   }


   //用户配置
   @Override
   @Bean
   protected UserDetailsService userDetailsService() {
      JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
      manager.setDataSource(dataSource);
      if (!manager.userExists("dhy")) {
         manager.createUser(User.withUsername("dhy").password("123").roles("admin").build());
      }
      if (!manager.userExists("大忽悠")) {
         manager.createUser(User.withUsername("大忽悠").password("123").roles("user").build());
      }
      return manager;
   }




   //角色继承
   @Bean
   RoleHierarchy roleHierarchy() {
      RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
      hierarchy.setHierarchy("ROLE_admin > ROLE_user");
      return hierarchy;
   }

}

点击退出登录:

回到设定的退出登录页面


LogoutSuccessHandler

如果上面的个性化配置,仍然满足不了您的应用需求。可能您的应用需要在logout的时候,做一些特殊动作,比如登录时长计算,清理业务相关的数据等等。你可以通过实现LogoutSuccessHandler 接口来实现你的业务逻辑。

代码语言:javascript
代码运行次数:0
运行
复制
@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    
    @Override
    public void onLogoutSuccess(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Authentication authentication) 
                                throws IOException, ServletException {
        //这里书写你自己的退出业务逻辑
        
        // 重定向到登录页
        response.sendRedirect("/login.html");
    }
}

然后进行配置使其生效,核心代码就是一行logoutSuccessHandler。注意logoutSuccessUrl不要与logoutSuccessHandler一起使用,否则logoutSuccessHandler将失效。

代码语言:javascript
代码运行次数:0
运行
复制
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
    
@Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
         http.logout()
             .logoutUrl("/signout")
             //.logoutSuccessUrl(``"/aftersignout.html"``)
             .deleteCookies("JSESSIONID")
              //自定义logoutSuccessHandler
             .logoutSuccessHandler(myLogoutSuccessHandler);   
   }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Security---退出功能详解
  • logout退出登录
    • 默认的logout做了什么?
    • 个性化配置
    • 演示
    • LogoutSuccessHandler
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档