spring security 登出操作 详细说明
阅读原文时间:2023年07月08日阅读:2

1.前言

这里专门 做 spring security 登出操作 的  详细记录

2.操作

(1)目录结构

(2)在security 拦截规则配置文件添加退出登录支持

源码

package com.example.security5500.securityConfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

//@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired  
private DbUserDetailsService dbUserDetailsService;

//拦截规则设置  
@Override  
protected void  configure(HttpSecurity http) throws Exception {  

// http
// .authorizeRequests()
// // 匹配 "/" 路径,不需要权限即可访问
// .antMatchers("/").permitAll()
// //匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
//// .antMatchers("/user/**").hasAuthority("USER")
// .and()
// //登录地址为 "/login",登录成功默认跳转到页面 "/hai"
// .formLogin().loginPage("/login").defaultSuccessUrl("/hai")
// //退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
// .and()
// //退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
// .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
// // 默认启用 CSRF ,必须post才可以访问/logout
http
//允许基于使用HttpServletRequest限制访问
.authorizeRequests()
//设置不拦截页面,可直接通过,路径访问 "/", "/index", "/home" 则不拦截,
//"/hhk/**" 的意思是 "/hhk" 及其以下所有路径
.antMatchers("/", "/index", "/home","/hhk/**")
//是允许所有的意思
.permitAll()
//其他页面都要拦截,【需要在最后设置这个】
.anyRequest().authenticated()
.and()
//设置自定义登录页面
.formLogin()
//指定自定义登录页面的访问虚拟路径
.loginPage("/login")
.permitAll()
.and()
// 添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效
// 来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
.logout()
// //指定的登出操作的虚拟路径,需要以post方式请求这个 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用户认证信息达到登出目的
.logoutUrl("/mylogout")
//登出成功后访问的地址
.logoutSuccessUrl("/home");
// .permitAll();
}

/\*\*  
 \* 添加 UserDetailsService, 实现自定义登录校验  
 \*/  
@Override  
protected void configure(AuthenticationManagerBuilder builder) throws Exception {  
    //注入用户信息,每次登录都会来这查询一次信息,因此不建议每次都向mysql查询,应该使用redis  
    builder.userDetailsService(dbUserDetailsService);  
}

/\*\*  
 \* 密码加密  
 \*/  
@Bean  
public static PasswordEncoder passwordEncoder() {  
    return NoOpPasswordEncoder.getInstance();  
}

}

(3)前端以表单的形式登出

3.测试

启动后,

直接 点击 登出即可

如果把不配置security 的拦截规则 ,将会默认使用get 方式 请求   /logout  来登出  ,会进入一个界面 ,需要鼠标点击

4.后端自定义登出

package com.example.security5500.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class UserController {

//登出操作  
@RequestMapping({"/doLogout"})  
public String logout(HttpServletRequest request, HttpServletResponse response) {  
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
    if (auth != null) {//清除认证  
        new SecurityContextLogoutHandler().logout(request, response, auth);  
    }  
    //重定向到指定页面  
    return "redirect:/login";  
}

}

请求这个也可以登出 ,原理是获取授权对象然后清除认证,再重定向到指定页面