SpringBoot+Spring Security退出登陸/自定義退出

本文在的Spring Boot + Spring Security權限控制 基礎上搭建退出登陸html

Spring Security默認的退出登陸URL爲/logout,退出登陸後,Spring Security會作以下處理:git

1.使當前的Sesion失效;github

2.清除與當前用戶關聯的RememberMe記錄;spring

3.清空當前的SecurityContext;json

4.重定向到登陸頁。springboot

  • 自定義退出: 在Spring Security配置中添加自定義退出的url,推出成功後跳轉到 /signout/success(切記須要將其加入到無需認證的列表中)
@Component
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啓權限註解
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyAuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private MyAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private ValidateCodeFilter validateCodeFilter;
    @Autowired
    private UserDetailService userDetailService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private MyAuthenticationAccessDeniedHandler myAuthenticationAccessDeniedHandler;

    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(false);
        return jdbcTokenRepository;
    }
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加驗證碼校驗過濾器
                 .exceptionHandling()
                 .accessDeniedHandler(myAuthenticationAccessDeniedHandler)
                 .and()
                 .formLogin() // 表單登陸
                // http.httpBasic() // HTTP Basic
               .loginPage("/authentication/require") // 登陸跳轉 URL
                .loginProcessingUrl("/login") // 處理表單登陸 URL
                .failureHandler(authenticationFailureHandler) // 處理登陸失敗
                .successHandler(authenticationSuccessHandler)
                 .and()
                 .rememberMe() // 啓用rememberMe
                 .tokenRepository(persistentTokenRepository()) // 配置 token 持久化倉庫
                 .tokenValiditySeconds(3600) // remember 過時時間,單爲秒
                 .userDetailsService(userDetailService) // 處理自動登陸邏輯
                .and()
                .authorizeRequests() // 受權配置
                .antMatchers("/authentication/require",
                        "/login.html",
                        "/code/image",
                        "/signout/success").permitAll() // 無需認證的請求路徑
                .anyRequest()  // 全部請求
                .authenticated() // 都須要認證
                 .and()
                 .logout()
                 .logoutUrl("/signout") // 退出登陸的url
                 .logoutSuccessUrl("/signout/success") // 退出登陸成功跳轉的url
                 .deleteCookies("JSESSIONID") // 刪除名爲'JSESSIONID'的cookie
                .and().csrf().disable();
    }
}
  • 修改IndexController:
@RestController
public class IndexController {
    @GetMapping("index")

    public Object index(){
        return SecurityContextHolder.getContext().getAuthentication();
    }
    @GetMapping("/auth/admin")
    @PreAuthorize("hasAuthority('admin')")
    public String authenticationTest() {
        return "您擁有admin權限,能夠查看";
    }
    @GetMapping("/signout/success")
    public String logoutSuccess() {
        System.out.println("退出成功,請從新登陸");
        return "退出成功,請從新登陸";
    }
}

登錄成功:cookie

token表中:app

訪問http://localhost:6006/signout, 退出登陸:ide

token表中: ui

退出成功,請求重定向到了/signout/success

  • 使用自定義退出成功處理器來處理退出成功後的邏輯:

實現退出成功處理器:

@Component
public class MyLogOutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write("退出成功,請從新登陸");
    }
}

修改Security配置類,添加退出成功處理器:

@Component
@EnableGlobalMethodSecurity(prePostEnabled = true) // 開啓權限註解
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyAuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private MyAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private ValidateCodeFilter validateCodeFilter;
    @Autowired
    private UserDetailService userDetailService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private MyAuthenticationAccessDeniedHandler myAuthenticationAccessDeniedHandler;

    @Autowired
    private MyLogOutSuccessHandler myLogOutSuccessHandler;

    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(false);
        return jdbcTokenRepository;
    }
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) // 添加驗證碼校驗過濾器
                 .exceptionHandling()
                 .accessDeniedHandler(myAuthenticationAccessDeniedHandler)
                 .and()
                 .formLogin() // 表單登陸
                // http.httpBasic() // HTTP Basic
               .loginPage("/authentication/require") // 登陸跳轉 URL
                .loginProcessingUrl("/login") // 處理表單登陸 URL
                .failureHandler(authenticationFailureHandler) // 處理登陸失敗
                .successHandler(authenticationSuccessHandler)
                 .and()
                 .rememberMe() // 啓用rememberMe
                 .tokenRepository(persistentTokenRepository()) // 配置 token 持久化倉庫
                 .tokenValiditySeconds(3600) // remember 過時時間,單爲秒
                 .userDetailsService(userDetailService) // 處理自動登陸邏輯
                .and()
                .authorizeRequests() // 受權配置
                .antMatchers("/authentication/require",
                        "/login.html",
                        "/code/image",
                        "/signout/success").permitAll() // 無需認證的請求路徑
                .anyRequest()  // 全部請求
                .authenticated() // 都須要認證
                 .and()
                 .logout()
                 .logoutUrl("/signout") // 退出登陸的url
                 // .logoutSuccessUrl("/signout/success")
                 .logoutSuccessHandler(myLogOutSuccessHandler) // 配置退出成功處理騎
                 .deleteCookies("JSESSIONID") // 刪除名爲'JSESSIONID'的cookie
                .and().csrf().disable();
    }
}

訪問http://localhost:6006/signout, 退出成功後:

本文代碼運行正常

本文源代碼:https://github.com/ttdys/springboot/tree/master/springboot_security/06_logout

相關文章
相關標籤/搜索