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; |
| |
| |
| |
| |
| |
| |
| public class JwtUtil { |
| |
| private static String TOKEN = "token!Q@W3e4r"; |
| |
| |
| 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(); |
| } |
| |
| |
| |
| public static void verify(String token){ |
| JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token); |
| } |
| |
| |
| |
| public static DecodedJWT getToken(String token){ |
| return JWT.require(Algorithm.HMAC256(TOKEN)).build().verify(token); |
| } |
| |
| |
| 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); |
| |
| String str = new String(bytes); |
| HashMap hashMap = JSON.parseObject(str, HashMap.class); |
| Integer aid = Integer.parseInt(hashMap.get("aid").toString()); |
| return aid; |
| } |
| |
| |
| 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; |
| |
| |
| |
| |
| |
| |
| public class MyInterceptor implements HandlerInterceptor { |
| |
| @Autowired |
| private JwtUtil jwtUtil; |
| |
| @Override |
| public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
| |
| |
| 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; |
| |
| |
| |
| |
| |
| |
| @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; |
| |
| |
| |
| |
| |
| |
| @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; |
| |
| |
| export const requestMethodName = (param) => requests({ |
| url: `/blog/userCancelCollectBlog?blogAid=${param}`, |
| method: 'post', |
| headers: { |
| token: localStorage.getItem('token'), |
| } |
| }); |
| |
| |
| export const queryUserConcernList = (data) => requests({ |
| url: `/user/queryUserConcernList`, |
| method: 'get', |
| params: data, |
| headers: { |
| token: localStorage.getItem('token'), |
| } |
| }); |
| |
| |
| export const sendMessageToChatObject = (params) => requests({ |
| url: `/chat/sendMessageToChatObject`, |
| method: 'post', |
| data: params, |
| headers: { |
| token: localStorage.getItem('token'), |
| } |
| }); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!