Spring|Spring Security前后分离校验token的实现方法

目录

  • 前言
  • token配置
    • 引入JWT依赖文件
    • 配置token管理器类
  • security配置
    • 配置未登录处理类
    • 配置无权限处理类
    • 配置登出操作处理类
    • 配置token认证过滤器
    • 配置token权限校验过滤器
    • 自定义加密类
    • 配置UserDetailService
    • 配置数据库User对象映射类
    • 配置UserDetailService使用的SecurityUser类
    • 配置mybatis-plus
    • 配置security配置类
    • 配置几个测试接口
    • Md5加密工具类
  • 测试
    • 首先测试登录
    • 测试存在权限的接口
    • 测试不存在权限的接口
    • 测试登出
    • 测试不需要权限的接口
  • 数据库sql脚本
    • 代码下载

      前言 之前采取项目中嵌套html页面,实现基本的登录校验权限校验登出操作记住我等功能试下。
      但是,现在的开发基本都是前后分离样式,后端并不需要配置登录页的操作。
      如何才能做到前后分离,同时也能支持登录token校验呢,本篇博客详细说明。

      token配置 本次token生成采取jwt的方式。

      引入JWT依赖文件
      com.auth0java-jwt3.10.3


      配置token管理器类
      自定一个Token生成和从token中解析用户名的一个类,并交给Spring管理。
      package security.config; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import org.springframework.stereotype.Component; import java.util.Calendar; import java.util.HashMap; @Componentpublic class TokenJwtManager {// 设置token时间private int tokenEcpiration = 24*60*60*1000; // 毫秒24h// 编码密钥private String tokenSignKey = "123456"; // 1、根据用户名生成tokenpublic String createToken(String userName){Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND, tokenEcpiration); String userName1 = JWT.create().withHeader(new HashMap<>()).withClaim("userName", userName).withExpiresAt(calendar.getTime()) // 过期时间.sign(Algorithm.HMAC256(tokenSignKey)); // 签名return userName1; }// 2、根据token得到用户名信息public String getUserName(String token){JWTVerifier build = JWT.require(Algorithm.HMAC256(tokenSignKey)).build(); DecodedJWT verify = build.verify(token); Claim userName = verify.getClaim("userName"); return userName.asString(); public static void main(String[] args) {String ss = new TokenJwtManager().createToken("1111111"); System.out.println(ss); System.out.println(new TokenJwtManager().getUserName(ss)); }


      security 配置
      配置未登录处理类
      package security.config.handler; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * 未登录 */@Component@Slf4jpublic class MyUnAuthEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {log.info("======= commence ==="); // 返回请求端Map resultMap = new HashMap<>(); // 保存数据resultMap.put("code","10000"); resultMap.put("msg","当前账户未登录"); resultMap.put("data",new HashMap<>()); // 设置返回消息类型httpServletResponse.setHeader("Content-type", "text/html; charset=UTF-8"); httpServletResponse.setCharacterEncoding("utf-8"); httpServletResponse.setContentType("application/json; charset=UTF-8"); // 返回给请求端PrintWriter writer= httpServletResponse.getWriter(); writer.write(resultMap.toString()); writer.close(); }}

      【Spring|Spring Security前后分离校验token的实现方法】
      配置无权限处理类
      package security.config.handler; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * 无权访问配置(前后分离) */@Component// 交给spring管理public class MyAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {Map resultMap = new HashMap<>(); // 保存数据resultMap.put("code","403"); resultMap.put("msg","无权访问"); resultMap.put("data",null); // 设置返回消息类型httpServletResponse.setHeader("Content-type", "text/html; charset=UTF-8"); httpServletResponse.setCharacterEncoding("utf-8"); httpServletResponse.setContentType("application/json; charset=UTF-8"); // 返回给请求端PrintWriter writer = httpServletResponse.getWriter(); writer.write(resultMap.toString()); writer.flush(); writer.close(); }}


      配置登出操作处理类
      package security.config.handler; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.stereotype.Component; import security.config.TokenJwtManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * 登出 */@Component@Slf4jpublic class MyLogoutHandler implements LogoutHandler {@Autowiredprivate TokenJwtManager tokenJwtManager; //public MyLogoutHandler(TokenJwtManager tokenJwtManager) {//this.tokenJwtManager = tokenJwtManager; //}@Overridepublic void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {// 1、从header中获取tokenString token = httpServletRequest.getHeader("token"); log.info("token信息为{}",token); String userName = tokenJwtManager.getUserName(token); log.info("从token获取userName信息为{}",token); // redis 移除登录信息等逻辑// xxxxx// 2、返回请求端Map resultMap = new HashMap<>(); // 保存数据resultMap.put("code","200"); resultMap.put("msg",userName+"登录成功"); resultMap.put("data",new HashMap<>()); // 设置返回消息类型httpServletResponse.setHeader("Content-type", "text/html; charset=UTF-8"); httpServletResponse.setCharacterEncoding("utf-8"); httpServletResponse.setContentType("application/json; charset=UTF-8"); // 返回给请求端PrintWriter writer = null; try {writer = httpServletResponse.getWriter(); writer.write(resultMap.toString()); writer.flush(); writer.close(); } catch (IOException e) {e.printStackTrace(); }}}


      配置token认证过滤器
      package security.filter; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Component; import security.config.TokenJwtManager; import security.vo.SecurityUser; import security.vo.User; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; // 这里交给spring管理会报错@Slf4jpublic class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {private TokenJwtManager tokenJwtManager; private AuthenticationManager authenticationManager; public TokenLoginFilter(TokenJwtManager tokenJwtManager, AuthenticationManager authenticationManager) {this.tokenJwtManager = tokenJwtManager; this.authenticationManager = authenticationManager; this.setPostOnly(false); // 关闭登录只允许 post// 设置登陆路径,并且post请求this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/user/login","POST")); }// 1、获取登录页传递来的账户和密码信息@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){log.info("==== attemptAuthentication======"); String userName = request.getParameter("userName"); String pwd = request.getParameter("passWord"); log.info("userName:{},pwd:{}",userName,pwd); return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName,pwd,new ArrayList<>())); // 2、认证成功调用@Autowiredprotected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)throws IOException, ServletException {log.info("==== successfulAuthentication======"); // 认证成功之后,获取认证后的用户基本信息SecurityUser securityUser = (SecurityUser) authResult.getPrincipal(); // 根据用户名生成对应的tokenString token = tokenJwtManager.createToken(securityUser.getUsername()); // token信息存于redis、数据库、缓存等// 返回成功Map resultMap = new HashMap<>(); // 保存数据resultMap.put("code","200"); resultMap.put("msg","登录成功"); resultMap.put("data",token); // 设置返回消息类型response.setHeader("Content-type", "text/html; charset=UTF-8"); response.setCharacterEncoding("utf-8"); response.setContentType("application/json; charset=UTF-8"); // 返回给请求端PrintWriter writer = response.getWriter(); writer.write(resultMap.toString()); writer.flush(); writer.close(); // 3、认证失败调用的方法protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)log.info("==== unsuccessfulAuthentication======"); resultMap.put("code","500"); resultMap.put("msg","登录验证失败"); resultMap.put("data",new HashMap<>()); }


      配置token权限校验过滤器
      package security.filter; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.stereotype.Component; import security.config.TokenJwtManager; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * token 校验 */@Slf4j//@Component // 交给 spring 会报错public class TokenAuthFilter extends BasicAuthenticationFilter {private TokenJwtManager tokenJwtManager; public TokenAuthFilter(AuthenticationManager authenticationManager, TokenJwtManager tokenJwtManager) {super(authenticationManager); this.tokenJwtManager = tokenJwtManager; }@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {log.info("====doFilterInternal==========token校验"); //获取当前认证成功用户权限信息UsernamePasswordAuthenticationToken authRequest = getAuthentication(request); if(authRequest != null){// 有权限,则放入权限上下文中SecurityContextHolder.getContext().setAuthentication(authRequest); }// 执行下一个 filter 过滤器链chain.doFilter(request,response); private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {log.info("==== getAuthentication ====="); //从header获取tokenString token = request.getHeader("token"); log.info("token:{}",token); if(token != null) {//从token获取用户名String username = tokenJwtManager.getUserName(token); log.info("解析token获取userName为:{}",username); // 数据库获取权限信息// 本次模拟List permissionValueList = Arrays.asList("admin","select"); Collection authority = new ArrayList<>(); for(String permissionValue : permissionValueList) {SimpleGrantedAuthority auth = new SimpleGrantedAuthority(permissionValue); authority.add(auth); }return new UsernamePasswordAuthenticationToken(username,token,authority); return null; }


      自定义加密类
      package security.config; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import security.utils.Md5Utils; /** * 密码加密、比对 */@Component // bean@Slf4jpublic class DefaultPwdEndoder implements PasswordEncoder {/*** 加密* @param charSequence* @return*/@Overridepublic String encode(CharSequence charSequence) {log.info("==== encode ===="); log.info("charSequence 为 {}",charSequence); log.info("charSequence md5为 {}",Md5Utils.md5(charSequence.toString())); return Md5Utils.md5(charSequence.toString()); }* 进行密码比对* @param charSequence 不加密* @param encodePwd加密public boolean matches(CharSequence charSequence, String encodePwd) {log.info("==== matches ===="); log.info("charSequence:{}",charSequence); log.info("charSequenceMd5:{}",Md5Utils.md5(charSequence.toString())); log.info("encodePwd:{}",encodePwd); return encodePwd.equalsIgnoreCase(Md5Utils.md5(charSequence.toString())); }


      配置UserDetailService
      package security.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import security.mapper.UserMapper; import security.vo.SecurityUser; import security.vo.User; import java.util.Arrays; import java.util.List; /** * security 登录信息和权限获取类 */@Service("userDetailsService")@Slf4jpublic class UserDetailService implements UserDetailsService {// 注入Usermapper@Autowiredprivate UserMapper userMapper; @Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {log.info("====== loadUserByUsername ======"); // 通过username查询数据库获取用户信息QueryWrapper userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("username",userName); User user = userMapper.selectOne(userQueryWrapper); // 判断用户是否存在if(user == null){throw new UsernameNotFoundException("账户信息不存在!"); }// 存在对应的用户信息,则将其封装,丢给security自己去解析log.info("user:{}",user); // 权限暂时不查数据库List admin = Arrays.asList("ROLE_user,ROLE_admin,admin"); // 将数据封装给 SecurityUser ,因为 SecurityUser 是 UserDetails 的子类SecurityUser securityUser = new SecurityUser(); securityUser.setPermissionValueList(admin); securityUser.setUser(user); log.info("securityUser:{}",securityUser.toString()); return securityUser; }}


      配置数据库User对象映射类
      package security.vo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data@NoArgsConstructor@AllArgsConstructorpublic class User implements Serializable {private static final long serialVersionUID = -5461108964440966122L; private Integer id; private String username; private String password; private Integer enabled; private Integer locked; }


      配置UserDetailService使用的SecurityUser类
      package security.vo; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.StringUtils; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * UserDetailService 使用该类,该类必须是 UserDetails 的子类 */@Datapublic class SecurityUser implements UserDetails {// 登录用户的基本信息private User user; //当前权限private List permissionValueList; public SecurityUser() {}public SecurityUser(User user) {if (user != null) {this.user = user; }@Overridepublic Collection getAuthorities() {Collection authorities = new ArrayList<>(); permissionValueList.forEach(permission ->{if(!StringUtils.isEmpty(permission)){SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permission); authorities.add(authority); }}); return authorities; public String getPassword() {return user.getPassword(); public String getUsername() {return user.getUsername(); public boolean isAccountNonExpired() {return true; public boolean isAccountNonLocked() {public boolean isCredentialsNonExpired() {public boolean isEnabled() {}


      配置mybatis-plus
      首先,需要配置application.properties数据库连接源。
      spring.datasource.username=rootspring.datasource.password=rootspring.datasource.url=jdbc:mysql://106.55.137.66:3306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverserver.port=80

      其次,需要配置Mapper类,查询数据库获取基本数据信息。
      package security.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.springframework.stereotype.Repository; import security.vo.User; @Repositorypublic interface UserMapper extends BaseMapper {}


      配置security配置类
      package security.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import security.config.handler.*; import security.filter.TokenAuthFilter; import security.filter.TokenLoginFilter; import security.service.UserDetailService; /** * security 配置类 */@Configuration@EnableGlobalMethodSecurity(prePostEnabled = true)// 方法增加权限public class MyTokenSecurityConfig extends WebSecurityConfigurerAdapter {// 将 UserDetailService 注入,使其去查询数据库@Autowiredprivate UserDetailService userDetailsService; // token 生成器@Autowiredprivate TokenJwtManager tokenManager; // 自定义密码加密解密@Autowiredprivate DefaultPwdEndoder defaultPwdEndoder; // 未登录handler@Autowiredprivate MyUnAuthEntryPoint myUnAuthEntryPoint; // 无权限@Autowiredprivate MyAccessDeniedHandler myAccessDeniedHandler; //登出handler处理@Autowiredprivate MyLogoutHandler myLogoutHandler; // 登录失败@Autowiredprivate LoginFailedHandler loginFailedHandler; // 登录成功@Autowiredprivate LoginSuccessHandler loginSuccessHandler; /*** 登录时,从数据库获取基本信息和权限信息* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 设置 userDetailsService 和 密码解析auth.userDetailsService(userDetailsService).passwordEncoder(defaultPwdEndoder); }/*** 配置访问过滤* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.exceptionHandling().authenticationEntryPoint(myUnAuthEntryPoint) // 未登录 handler.accessDeniedHandler(myAccessDeniedHandler) // 无权限.and().csrf().disable() // 关闭 csrf 跨域请求.formLogin().loginProcessingUrl("/user/login")// 设定登录请求接口.usernameParameter("userName").passwordParameter("passWord")//.successHandler(loginSuccessHandler) // 因为有了 TokenLoginFilter 配置过滤器,此处配置没用//.failureHandler(loginFailedHandler) // 因为有了 TokenLoginFilter 配置过滤器,此处配置没用.permitAll().and().authorizeRequests() // 请求设置.antMatchers("/test").permitAll() // 配置不需要认证的接口.anyRequest().authenticated() // 任何请求都需要认证.and().logout() // logout设定.logoutUrl("/logouts")//退出请求/logouts 未定义,交给自定义handler实现功能.addLogoutHandler(myLogoutHandler) // 登出 myLogoutHandler 处理.and().addFilter(new TokenLoginFilter(tokenManager,authenticationManager())) // 认证交给 自定义 TokenLoginFilter 实现.addFilter(new TokenAuthFilter(authenticationManager(),tokenManager)).httpBasic(); }/*** 配置不需要验证的访问路径* @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) throws Exception {//web.ignoring().antMatchers("/test","/user/login"); web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**"); }}


      配置几个测试接口
      package security.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class TestController {@RequestMapping("/test")public String test(){return "不需要认证就能访问"; }}

      package security.controller; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class UserController {@RequestMapping("/user/test1")@PreAuthorize("hasAnyAuthority('admin','user')")public String test1(){return "需要认证的 /user/test1"; }@RequestMapping("/user/test2")@PreAuthorize("hasAnyAuthority('test')")public String test2(){return "需要认证的 /user/test2"; }


      Md5加密工具类
      package security.utils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; /** * 加密工具类 */public class Md5Utils {public static String md5(String str) {try {MessageDigest md = MessageDigest.getInstance("MD5"); md.update(str.getBytes()); byte b[] = md.digest(); str = byteToStr(b); } catch (Exception e) {e.printStackTrace(); }return str; }public static String byteToStr(byte[] b){int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) {i = b[offset]; //System.out.println(i); if (i < 0)i += 256; if (i < 16)buf.append("0"); buf.append(Integer.toHexString(i)); return buf.toString(); /*** 传入文本内容,返回 SHA-256 串** @param strText* @return*/public static String SHA256(final String strText){return SHA(strText, "SHA-256"); public static String SHA1(final String strText)return SHA(strText, "SHA-1"); * 传入文本内容,返回 SHA-512 串public static String SHA512(final String strText)return SHA(strText, "SHA-512"); * 字符串 SHA 加密private static String SHA(final String strText, final String strType)// 返回值String strResult = null; // 是否是有效字符串if (strText != null && strText.length() > 0){try{// SHA 加密开始MessageDigest messageDigest = MessageDigest.getInstance(strType); // 传入要加密的字符串messageDigest.update(strText.getBytes("utf-8")); // 得到 byte 类型的结果byte byteBuffer[] = messageDigest.digest(); strResult = byteToStr(byteBuffer); }catch (NoSuchAlgorithmException e)e.printStackTrace(); }catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blockreturn strResult; public static String base64(String str){String baseStr = null; Base64.Encoder encoder = Base64.getEncoder(); byte[] textByte; textByte = str.getBytes("UTF-8"); baseStr = encoder.encodeToString(textByte); } catch (UnsupportedEncodingException e) {return baseStr; public static void main(String[] args) {String password = "bunana1"; System.out.println(md5(password)); //String base64 = base64(sha512); //System.out.println(base64); //String pwd1 = md5(base64); //System.out.println(pwd1); }


      测试 测试采取ApiPost 工具,让测试更接近前后分离。

      首先测试登录
      Post
      localhost/user/login
      账号密码有一个不对时。
      Spring|Spring Security前后分离校验token的实现方法
      文章图片

      正确的账号密码
      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      测试存在权限的接口
      localhost/user/test1
      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      测试不存在权限的接口
      localhost/user/test2
      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      测试登出
      localhost/logouts
      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      测试不需要权限的接口
      localhost/test
      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      数据库sql脚本
      CREATE TABLE `user` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, -- 主键`username` varchar(255) DEFAULT NULL,-- 用户名`password` varchar(255) DEFAULT NULL,-- 用户密码`enabled` tinyint(1) DEFAULT '1',-- 是否启用 1-启用 0-未启用`locked` tinyint(1) DEFAULT '0',-- 是否被锁 1-已锁 0-未锁PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

      数据为:
      insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS","1babad058e03c5296a94a5a8d7d6dd8a",1,0); -- bunana 的md5 值insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS2","0b13310f8db2dc22e7ddd0cdc5f0a61a",1,0); -- bunana1 的md5 值insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS3","b3fbcd9c9d97e47f263a19a0e01efc7d",1,0); -- bunana2 的md5 值

      Spring|Spring Security前后分离校验token的实现方法
      文章图片


      代码下载 springboot-security-10-qianhou
      gitee 代码下载地址
      到此这篇关于Spring Security前后分离校验token的文章就介绍到这了,更多相关Spring Security校验token内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

        推荐阅读