Spring?Security前后分離校驗token的實現(xiàn)方法
前言
之前采取項目中嵌套html頁面,實現(xiàn)基本的登錄校驗、權限校驗、登出操作、記住我等功能試下。
但是,現(xiàn)在的開發(fā)基本都是前后分離樣式,后端并不需要配置登錄頁的操作。
如何才能做到前后分離,同時也能支持登錄和token校驗呢,本篇博客詳細說明。
token配置
本次token生成采取jwt的方式。
引入JWT依賴文件
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
配置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、根據(jù)用戶名生成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、根據(jù)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<String,Object> resultMap = new HashMap<>();
// 保存數(shù)據(jù)
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<String,Object> resultMap = new HashMap<>();
// 保存數(shù)據(jù)
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<String,Object> resultMap = new HashMap<>();
// 保存數(shù)據(jù)
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();
// 根據(jù)用戶名生成對應的token
String token = tokenJwtManager.createToken(securityUser.getUsername());
// token信息存于redis、數(shù)據(jù)庫、緩存等
// 返回成功
Map<String,Object> resultMap = new HashMap<>();
// 保存數(shù)據(jù)
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;
}
@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);
}
// 執(zhí)行下一個 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);
// 數(shù)據(jù)庫獲取權限信息
// 本次模擬
List<String> permissionValueList = Arrays.asList("admin","select");
Collection<GrantedAuthority> 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
@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查詢數(shù)據(jù)庫獲取用戶信息
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("username",userName);
User user = userMapper.selectOne(userQueryWrapper);
// 判斷用戶是否存在
if(user == null){
throw new UsernameNotFoundException("賬戶信息不存在!");
}
// 存在對應的用戶信息,則將其封裝,丟給security自己去解析
log.info("user:{}",user);
// 權限暫時不查數(shù)據(jù)庫
List<String> admin = Arrays.asList("ROLE_user,ROLE_admin,admin");
// 將數(shù)據(jù)封裝給 SecurityUser ,因為 SecurityUser 是 UserDetails 的子類
SecurityUser securityUser = new SecurityUser();
securityUser.setPermissionValueList(admin);
securityUser.setUser(user);
log.info("securityUser:{}",securityUser.toString());
return securityUser;
}
}配置數(shù)據(jù)庫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<String> permissionValueList;
public SecurityUser() {
}
public SecurityUser(User user) {
if (user != null) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> 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數(shù)據(jù)庫連接源。
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類,查詢數(shù)據(jù)庫獲取基本數(shù)據(jù)信息。
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<User> {
}配置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 注入,使其去查詢數(shù)據(jù)庫
@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;
/**
* 登錄時,從數(shù)據(jù)庫獲取基本信息和權限信息
* @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實現(xiàn)功能
.addLogoutHandler(myLogoutHandler) // 登出 myLogoutHandler 處理
.and()
.addFilter(new TokenLoginFilter(tokenManager,authenticationManager())) // 認證交給 自定義 TokenLoginFilter 實現(xiàn)
.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.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 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 工具,讓測試更接近前后分離。
首先測試登錄
Post
localhost/user/login
賬號密碼有一個不對時。

正確的賬號密碼

測試存在權限的接口
localhost/user/test1

測試不存在權限的接口
localhost/user/test2

測試登出
localhost/logouts

測試不需要權限的接口
localhost/test

數(shù)據(jù)庫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;
數(shù)據(jù)為:
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
到此這篇關于Spring Security前后分離校驗token的文章就介紹到這了,更多相關Spring Security校驗token內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java使用wait/notify實現(xiàn)線程間通信上篇
wait()和notify()是直接隸屬于Object類,也就是說所有對象都擁有這一對方法,下面這篇文章主要給大家介紹了關于使用wait/notify實現(xiàn)線程間通信的相關資料,需要的朋友可以參考下2022-12-12
Java基于Calendar類輸出指定年份和月份的日歷代碼實例
這篇文章主要介紹了Java 使用Calendar類輸出指定年份和月份的日歷,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-02-02
基于swagger參數(shù)與實體中參數(shù)不一致的原因分析
這篇文章主要介紹了基于swagger參數(shù)與實體中參數(shù)不一致的原因分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11

