SpringBoot JWT
JWT是一种鉴权机制,实现前后端分离登陆和权限的一种解决方式,用户在登陆之后后端生成token传到前端,以后每次的请求都携带着token到后端验证,如果过期或者失效就要求重新登陆。
具体详情请看:https://blog.csdn.net/weixin_53312997/article/details/126938201
后端如何实现token
首先导个依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
其次建立一个jwt工具类
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Base64;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* create by fzg
* 2021/10/12 9:41
*/
public class JwtUtil {
private static String TOKEN = "token!Q@W3e4r";
/*** 生成token * @param map //传入payload * @return 返回token */
public static String getToken(Map<String,String> map){
JWTCreator.Builder builder = JWT.create();
map.forEach((k,v)->{ builder.withClaim(k,v); });
Calendar instance = Calendar.getInstance();
instance.add(Calendar.HOUR,24*3);
builder.withExpiresAt(instance.getTime());
return builder.sign(Algorithm.HMAC256(TOKEN)).toString();
}/**
7.整合springboot * 验证token * @param token * @return
* @return*/
public static void verify(String token){
JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
}
/*** 获取token中payload * @param token * @return */
public static DecodedJWT getToken(String token){
return JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token);
}
// token 获取id
public static Integer getTokenId(String token){
DecodedJWT untoken = JwtUtil.getToken(token);
String payload = untoken.getPayload();
Base64.Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(payload);
//System.out.println("BASE64解密:" + new String(bytes));
String str = new String(bytes);
HashMap hashMap = JSON.parseObject(str, HashMap.class);
Integer aid = Integer.parseInt(hashMap.get("aid").toString());
return aid;
}
// 解密token
public static String getClaim(String token, String key) {
DecodedJWT decodedJWT = JWT.decode(token);
Claim value = decodedJWT.getClaim(key);
return value.asString();
}
}
请求拦截器
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fzg.common.tool.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* create by fzg
* 2021/10/12 10:47
*/
public class MyInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从前端请求中获取token
String token = request.getHeader("token");
Map<String,Object> map = new HashMap<>();
if (token == null){
map.put("state",false);
map.put("msg","token为空");
}else {
try {
JwtUtil.verify(token);
Integer aid = Integer.parseInt(JwtUtil.getClaim(token,"aid"));
request.setAttribute("aid",aid);
return true;
}catch (TokenExpiredException e){
map.put("state",false);
map.put("msg","token已过期!");
}catch (SignatureVerificationException e){
map.put("state",false);
map.put("msg","签名错误!");
}catch (AlgorithmMismatchException e){
map.put("state",false);
map.put("msg","加密算法不匹配");
}catch (Exception e){
map.put("state",false);
map.put("msg","无效token!");
}
}
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
拦截配置
拦截所有请求,除了用户登陆和注册,其他都需要经过MyInterceptor请求拦截器
import com.fzg.common.interceptor.MyInterceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* create by fzg
* 2021/10/12 12:02
*/
@Component
public class InceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/user/register")
.excludePathPatterns("/user/login");
}
}
跨域配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* create by fzg
* 2021/10/9 10:57
*/
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.addExposedHeader("token");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
用户登陆成功后后端将token传到前端
HashMap<String, String> map = new HashMap<>();
map.put("aid",user.getAid().toString());
String token = JwtUtil.getToken(map);
前端的所有请求携带token
//引入axios,进行二次封装
import axios from 'axios'
const requests = axios.create({
// 配置对象
//基础路径,发送请求的时候,路径当中会出现api
baseURL: 'http://localhost:8001',
// baseURL: 'http://43.142.195.65:8001',
//代表请求超时的时间5秒
timeout: 5000,
});
export default requests;
// 前端拿到之后存储到localStorage,
// 发送请求的时候再携带token
export const requestMethodName = (param) => requests({
url: `/blog/userCancelCollectBlog?blogAid=${param}`,
method: 'post',
headers: {
token: localStorage.getItem('token'),
}
});
// get请求(例子)
export const queryUserConcernList = (data) => requests({
url: `/user/queryUserConcernList`,
method: 'get',
params: data,
headers: {
token: localStorage.getItem('token'),
}
});
// post请求例子
export const sendMessageToChatObject = (params) => requests({
url: `/chat/sendMessageToChatObject`,
method: 'post',
data: params,
headers: {
token: localStorage.getItem('token'),
}
});