29、OSPF配置实验之被动接口
298
2022-08-25
Spring Security前后分离校验token的实现方法
目录前言token配置引入JWT依赖文件配置token管理器类security配置配置未登录处理类配置无权限处理类配置登出操作处理类配置token认证过滤器配置token权限校验过滤器自定义加密类配置UserDetailService配置数据库User对象映射类配置UserDetailService使用的SecurityUser类配置mybatis-plus配置security配置类配置几个测试接口Md5加密工具类测试首先测试登录测试存在权限的接口测试不存在权限的接口测试登出测试不需要权限的接口数据库sql脚本代码下载
前言
之前采取项目中嵌套html页面,实现基本的登录校验、权限校验、登出操作、记住我等功能试下。
但是,现在的开发基本都是前后分离样式,后端并不需要配置登录页的操作。
如何才能做到前后分离,同时也能支持登录和token校验呢,本篇博客详细说明。
token配置
本次token生成采取jwt的方式。
引入JWT依赖文件
配置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;
@Component
public class TokenJwtManager {
// 设置token时间
private int tokenEcpiration = 24*60*60*1000; // 毫秒 24h
// 编码密钥
private String tokenSignKey = "123456";
// 1、根据用户名生成token
public 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
@Slf4j
public class MyUnAuthEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
log.info("======= commence ===");
// 返回请求端
Map
// 保存数据
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();
}
}
配置无权限处理类
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 {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
Map
// 保存数据
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
@Slf4j
public class MyLogoutHandler implements LogoutHandler {
@Autowired
private TokenJwtManager tokenJwtManager;
// public MyLogoutHandler(TokenJwtManager tokenJwtManager) {
// this.tokenJwtManager = tokenJwtManager;
// }
@Override
public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
// 1、从header中获取token
String token = httpServletRequest.getHeader("token");
log.info("token信息为 {}",token);
String userName = tokenJwtManager.getUserName(token);
log.info("从token获取userName信息为 {}",token);
// redis 移除登录信息等逻辑
// xxxxx
// 2、返回请求端
Map
// 保存数据
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管理会报错
@Slf4j
public 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、获取登录页传递来的账户和密码信息
@Override
public 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、认证成功调用
@Autowired
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
log.info("==== successfulAuthentication ======");
// 认证成功之后,获取认证后的用户基本信息
SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
// 根据用户名生成对应的token
String token = tokenJwtManager.createToken(securityUser.getUsername());
// token信息存于redis、数据库、缓存等
// 返回成功
http:// Map
// 保存数据
resultMap.put("code","200");
resultMap.put("msg","登录成功");
resultMap.put("data",token);
// 设置返回消息类型
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.http://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.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;
}
@Override
protected 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获取token
String token = request.getHeader("token");
log.info("token:{}",token);
if(token != null) {
//从token获取用户名
String username = tokenJwtManager.getUserName(token);
log.info("解析token获取userName为:{}",username);
// 数据库获取权限信息
// 本次模拟
List
Collection
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
@Slf4j
public class DefaultPwdEndoder implements PasswordEncoder {
/**
* 加密
* @param charSequence
* @return
*/
@Override
public 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")
@Slf4j
public class UserDetailService implements UserDetailsService {
// 注入Usermapper
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
log.info("====== loadUserByUsername ======");
// 通过username查询数据库获取用户信息
QueryWrapper
userQueryWrapper.eq("username",userName);
User user = userMapper.selectOne(userQueryWrapper);
// 判断用户是否存在
if(user == null){
throw new UsernameNotFoundException("账户信息不存在!");
}
// 存在对应的用户信息,则将其封装,丢给security自己去解析
log.info("user:{}",user);
// 权限暂时不查数据库
List
// 将数据封装给 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
@AllArgsConstructor
public 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 的子类
*/
@Data
public class SecurityUser implements UserDetails {
// 登录用户的基本信息
private User user;
//当前权限
private List
public SecurityUser() {
}
public SecurityUser(User user) {
if (user != null) {
this.user = user;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
Collection
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=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://106.55.137.66:3306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=80
其次,需要配置Mapper类,查询数据库获取基本数据信息。
package security.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import security.vo.User;
@Repository
public 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 注入,使其去查询数据库
@Autowired
private UserDetailService userDetailsService;
// token 生成器
@Autowired
private TokenJwtManager tokenManager;
// 自定义密码加密解密
@Autowired
private DefaultPwdEndoder defaultPwdEndoder;
// 未登录handler
@Autowired
private MyUnAuthEntryPoint myUnAuthEntryPoint;
// 无权限
@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;
// 登出handler处理
@Autowired
private MyLogoutHandler myLogoutHandler;
// 登录失败
@Autowired
private LoginFailedHandler loginFailedHandler;
// 登录成功
@Autowired
private LoginSuccessHandler loginSuccessHandler;
/**
* 登录时,从数据库获取基本信息和权限信息
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 设置 userDetailsService 和 密码解析
auth.userDetailsService(userDetailsService).passwordEncoder(defaultPwdEndoder);
}
/**
* 配置访问过滤
* @param http
* @throws Exception
*/
@Override
protected 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
*/
@Override
public 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;
@RestController
public 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;
@RestController
public 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.Base6PETOCPA4;
/**
* 加密工具类
*/
public class Md5Utils {
public static String md5(String str) {
try {
MessageDhttp://igest 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 block
return 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 工具,让测试更接近前后分离。
首先测试登录
Postlocalhost/user/login
账号密码有一个不对时。
正确的账号密码
测试存在权限的接口
localhost/user/test1
测试不存在权限的接口
localhost/user/test2
测试登出
localhost/logouts
测试不需要权限的接口
localhost/test
数据库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 值
代码下载
springboot-security-10-qianhou
gitee 代码下载地址
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~