JWT-令牌加密
本文最后更新于22 天前,其中的信息可能已经过时,如有错误请发送邮件到qiqin-chang@qq.com

依赖:

<!--JWT 令牌加密-->
<dependency>
   <groupId>com.auth0</groupId>
   <artifactId>java-jwt</artifactId>
   <version>4.3.0</version>
</dependency>

工具包:

旧:

生成Token 获取用户信息:

package com.chang.utils;
​
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.chang.entity.Account;
import com.chang.service.impl.AdminServiceImpl;
import com.chang.service.impl.EmployeeServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
​
import java.util.Date;
​
@Component
public class TokenUtils {
​
    @Autowired
    AdminServiceImpl adminService;
    @Autowired
    EmployeeServiceImpl employeeService;
​
    static AdminServiceImpl staticAdminService;
    static EmployeeServiceImpl staticEmployeeService;
​
    //springboot工程启动后会加载这段代码
    @PostConstruct
    public void init(){
        staticAdminService = adminService;
        staticEmployeeService = employeeService;
    }
​
​
    /**
     * 生成token
     */
    public static String createToken(String data,String sign) {
        return JWT.create().withAudience(data) //将userId-role 保存到token里面,作为载荷
                .withExpiresAt(DateUtil.offsetDay(new Date(),1)) //1天后token过期
                .sign(Algorithm.HMAC256(sign)); //秘钥签名 以password 作为token的秘钥,HMAC256算法加密
    }
​
    /**
     * 获取当前登录用户信息
     */
    public static Account getCurrentUser() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token  = request.getHeader("token");
        if (StrUtil.isBlank(token)){
            token = request.getParameter("Token");
        }
        if (StrUtil.isBlank(token)){
            return null;
        }
        //拿到token的载荷数据
        String audience = JWT.decode(token).getAudience().get(0);
        String[] split = audience.split("-");
        String userId = split[0];
        String role = split[1];
        //根据token解析出来的userId去对应的表查询用户信息
        if ("ADMIN".equals(role)){
            return staticAdminService.selectById(Integer.valueOf(userId));
        } else if ("EMP".equals(role)) {
            return staticEmployeeService.selectById(Integer.valueOf(userId));
        }
​
        return null;
    }
}
​

Service层login方法中:

生成token并返回给前端:

String token = TokenUtils.createToken(dbAdmin.getId() + "-" + "ADMIN", dbAdmin.getPassword());
dbAdmin.setToken(token);

获取当前用户信息:

Account currentUser = TokenUtils.getCurrentUser();

新:

package com.chang.utils;
​
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chang.entity.Account;
import com.chang.service.impl.AdminServiceImpl;
import com.chang.service.impl.EmployeeServiceImpl;
import com.chang.service.impl.UserServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
​
import java.util.Date;
​
@Component
public class JWTUtils {
​
    private static final String sign = "chang_2025";
​
    @Autowired
    AdminServiceImpl adminService;
    @Autowired
    EmployeeServiceImpl employeeService;
    @Autowired
    UserServiceImpl userService;
​
    static AdminServiceImpl staticAdminService;
    static EmployeeServiceImpl staticEmployeeService;
    static UserServiceImpl staticUserService;
​
    //springboot工程启动后会加载这段代码
    @PostConstruct
    public void init(){
        staticAdminService = adminService;
        staticEmployeeService = employeeService;
        staticUserService = userService;
    }
​
    /**
     * 生成 Token
     */
    public static String createToken(Integer id, String role) {
        return JWT.create()
                .withClaim("id", id)
                .withClaim("role", role)               // 角色
                .withExpiresAt(DateUtil.offsetDay(new Date(), 1)) // 1天后过期
                .sign(Algorithm.HMAC256(sign));
    }
​
    /**
     * 获取用户信息
     * @return
     */
    public static Account getCurrentUser() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("Token");
        if (StrUtil.isBlank(token)) {
            token = request.getParameter("Token");
        }
        if (StrUtil.isBlank(token)) {
            return null; //只能进行静默处理
        }
​
        try {
            // 1. 验签
            DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(sign)).build().verify(token);
​
            // 2. 解析 payload
            Integer userId = decodedJWT.getClaim("id").asInt();
            String role = decodedJWT.getClaim("role").asString();
​
            // 根据角色查对应表
            if ("ADMIN".equals(role)) {
                return staticAdminService.selectById(userId); // 假设 username 是主键
            } else if ("EMP".equals(role)) {
                return staticEmployeeService.selectById(userId);
            } else if ("USER".equals(role)) {
                return staticUserService.selectById(userId);
            }
        } catch (Exception e) {
            return null;
        }
​
​
        return null;
    }
​
}

拦截器:

注册拦截器:

package com.chang.config;
​
import com.chang.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
​
@Configuration
public class WebConfig implements WebMvcConfigurer {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/register");
    }
    
    @Bean
    public JWTInterceptor jwtInterceptor() {
        return new JWTInterceptor();
    }
}

实现拦截器:

旧:

package com.chang.interceptor;
​
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.chang.entity.Account;
import com.chang.exception.CustomException;
import com.chang.service.AdminService;
import com.chang.service.EmployeeService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
​
@Component
public class JWTInterceptor implements HandlerInterceptor {
    
    @Autowired
    AdminService adminService;
    @Autowired
    EmployeeService employeeService;
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.从请求头中获取token
        String token = request.getHeader("Token");
        if (StrUtil.isEmpty(token)){
            //如果没拿到,从参数里再拿一次
            token = request.getParameter("Token");
        }
        //2.认证token
        if (StrUtil.isBlank(token)){
            throw new CustomException("401","您无权限操作");
        }
​
        Account account = null;
        try{
            //拿到token的载荷数据
            String audience = JWT.decode(token).getAudience().get(0);
            String[] split = audience.split("-");
            String userId = split[0];
            String role = split[1];
            //根据token解析出来的userId去对应的表查询用户信息
            if ("ADMIN".equals(role)){
                account = adminService.selectById(Integer.valueOf(userId));
            } else if ("EMP".equals(role)) {
                account = employeeService.selectById(Integer.valueOf(userId));
            }
        }catch (Exception e){
            throw new CustomException("401","您无权限操作");
        }
        if (account == null){
            throw new CustomException("401","您无权限操作");
        }
​
        //验证签名
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build();
            jwtVerifier.verify(token);
        }catch (Exception e){
            throw new CustomException("401","您无权限操作");
        }
        
        return true;
    }
}

新:

package com.chang.interceptor;
​
import cn.hutool.core.util.StrUtil;
import com.chang.entity.Account;
import com.chang.exception.CustomException;
import com.chang.utils.TokenUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
​
@Component
public class JWTInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.从请求头中获取token
        String token = request.getHeader("Token");
        if (StrUtil.isEmpty(token)){
            //如果没拿到,从参数里再拿一次
            token = request.getParameter("Token");
        }
​
        //2.认证token
        if (StrUtil.isBlank(token)){
            throw new CustomException("401", "未检测到登录凭证,请先登录");
        }
​
        Account account = TokenUtils.getCurrentUser();
        if (account == null) {
            throw new CustomException("401", "Token无效或已过期,请重新登录");
        }
​
        return true;
    }
}

前端:

设置拦截器:

utils包:

request.js:

添加请求头 处理错误信息:

import axios from 'axios';
import {ElMessage} from 'element-plus';
import router from "@/router/index.js";

const request = axios.create({
   baseURL:'http://localhost:9090',
   timeout:30000, //后台接口超时时间
})

//request 拦截器
//可以自动请求发送前对请求做的一些处理
request.interceptors.request.use(
   config => {
       config.headers['Content-Type'] = 'application/json;charset=utf-8';
       let user = JSON.parse(localStorage.getItem('chang-user')||'{}');
       config.headers['token'] = user.token
       return config;
  },
   error => {
       return Promise.reject(error);
  }
)

//response 拦截器
//可以在接口响应后统一处理结果
request.interceptors.response.use(
   response => {
       let res = response.data;
       //兼容服务端返回的字符串数据
       if (typeof res === 'string') {
           res = res ? JSON.parse(res) : res;
      }
       if (res.code === '401') {
           ElMessage.error(res.msg);
           router.push('/login');
      }else{
           return res;
      }
       return res;
  },
   error => {
       if (error.response.status === 404) {
           ElMessage.error('未找到请求接口')
      }else if (error.response.status === 500) {
           ElMessage.error('系统异常,请查看后端控制台报错')
      }else {
           console.error(error.message);
      }
       return Promise.reject(error);
  }
)

export default request;

拼接Token令牌:

eg:更改导出数据代码:

user:JSON.parse(localStorage.getItem('chang-user')||'{}'),
​
//导出数据
const exportData=()=>{
  let url =  `http://localhost:9090/employee/export`
  + `?Token=${data.user.token}`;
  //导出数据 是通过流的形式下载 excel   打开流的连接,浏览器会自动帮我们下载文件
  window.open(url);
}
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇