IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> springboot集成JWT -> 正文阅读

[Java知识库]springboot集成JWT

前言

JWT,全称JSON? Web Token,将用户信息加密到token中,服务器不保存任何用户信息,服务器通过使用保存的密匙验证token的正确性,只要正确就通过验证。

JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户

组成

一个token三部分组成,三部分用“.”分割,按顺序分为

1、头部(header)

  • 声明类型是jwt
  • 声明加密算法? 通常使用HMAC SHA256

2、载荷(payload)

3、签证(signature)

使用

1、导入pom依赖

<!--        jwt-->
        <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>

2、在utils包下新建TokenUtil类,生成token

使用userId作为载荷,以password作为秘钥

package com.aqya.utils;


import cn.hutool.core.date.DateUtil;
import com.aqya.service.IUserService;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import java.util.Date;

/**
 * @author 阿青呀
 * @date 2022/05/11 14:20
 **/

public class TokenUtils {

    /**
     * 生成  Token
     * @param userId
     * @param sign
     * @return
     */
    public static String getToken(String userId,String sign){
      return   JWT.create().withAudience(userId) // 将user  id 保存到token  作为载荷
                    .withExpiresAt(DateUtil.offsetHour(new Date(),2))   //2小时过期
                    .sign(Algorithm.HMAC256(sign));  //以password 作为 token密匙

    }

}

3、在userService里面设置token

在userDto加入字符型token字段,登录业务不需要原来所有的实体类数据,就自己再创建专门登入使用的类userDto,一般就是用户名密码之类必须的,然后将实体类的用户名密码拷贝到这个userDto之中,即下面的语句

  BeanUtil.copyProperties(userDto,one,true);

?userService如下

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.log.Log;
import com.aqya.common.Constants;
import com.aqya.controller.dto.UserDto;
import com.aqya.entity.User;
import com.aqya.exception.ServiceException;
import com.aqya.mapper.UserMapper;
import com.aqya.service.IUserService;
import com.aqya.utils.TokenUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.stereotype.Service;



/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author aqya
 * @since 2022-05-03
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private static final Log LOG = Log.get();

    @Override
    public UserDto login(UserDto userDto) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",userDto.getUsername());
        queryWrapper.eq("password",userDto.getPassword());
        User one;
        //查出多条语句
//        List<User> list = list(queryWrapper);
//        return list.size() != 0;

        //查到多个用户名密码一致,抓取异常
        try{
            one = getOne(queryWrapper);    //从数据库查询信息
        }catch (Exception e){
            LOG.error(e);
            throw new ServiceException(Constants.CODE_500,"系统错误");
        }
        return  one;
    }
        //业务异常
        if(one !=null){
            BeanUtil.copyProperties(one,userDto,true);
            //设置token
            String token = TokenUtils.getToken(one.getId().toString(), one.getPassword());
            userDto.setToken(token);
            return userDto;
        }else {
            throw new  ServiceException(Constants.CODE_600,"用户名或者密码错误");
        }

    }

}

4、在axous的request.js放开

    let user = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user"))  : null
    if(user){  //user存在  设置token
        config.headers['token'] = user.token;  // 设置请求头
    }

完整的request.js

import axios from 'axios'
import ElementUI from 'element-ui'
const request = axios.create({
    baseURL: 'http://localhost:8081',  // 注意!! 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,页面里面写接口的时候就不要加 '/api'了,否则会出现2个'/api',类似 '/api/api/user'这样的报错,切记!!!
    timeout: 5000,
    headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
    }
})

// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';

    let user = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user"))  : null
    if(user){  //user存在  设置token
        config.headers['token'] = user.token;  // 设置请求头
    }

return config
}, error => {
    return Promise.reject(error)
});

// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
    response => {
    let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
    return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
    res = res ? JSON.parse(res) : res
}
//当权限验证不通过时候,给出提示
if (res.code === '401'){
    ElementUI.Message({
        message: "请先登录",
        type: 'error'
    })
}
return res;
},
error => {
    console.log('err' + error) // for debug
    return Promise.reject(error)
}
)


export default request

这时候登录过后在浏览器的请求标头一个要有token

5、拦截器验证token信息

在Interceptor包下建立JWTInterceptor

JWTInterceptor 实现 HandlerInterceptor接口,重写preHandle方法

package com.aqya.config.interceptor;

import cn.hutool.core.util.StrUtil;
import com.aqya.common.Constants;
import com.aqya.entity.User;
import com.aqya.exception.ServiceException;
import com.aqya.service.IUserService;
import com.aqya.service.impl.UserServiceImpl;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 阿青呀
 * @date 2022/05/11 14:57
 **/
@Component
public class JWTInterceptor implements HandlerInterceptor {

    @Autowired
    private IUserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        String token = request.getHeader("token");

        //如果不是映射到方法,直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        //执行认证
        if(StrUtil.isBlank(token)){
            throw new ServiceException(Constants.CODE_401,"无token,请重新登录");
        }
        //获取token 的user  id
        String userId;
        try{
            userId = JWT.decode(token).getAudience().get(0);
        }catch (JWTDecodeException j){
            throw new ServiceException(Constants.CODE_401,"token验证失败");
        }

        //更加token中的userId查询数据库

        User user =  userService.getById(userId);
        if(user == null){
            throw new ServiceException(Constants.CODE_401,"用户不存在,请重新登录");
        }

        //用户密码加签验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try{
            jwtVerifier.verify(token);  //验证token
        }catch (JWTVerificationException j){
            throw new ServiceException(Constants.CODE_401,"token验证失败,请重新登录");
        }
        return true;
    }
}

6、注册拦截器重写addInterceptors方法

package com.aqya.config;

import com.aqya.config.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;

/**
 * @author 阿青呀
 * @date 2022/05/11 15:13
 **/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**")  //拦截所有请求,通过验证token是否合法决定是否登录
                .excludePathPatterns("/user/login","/user/register","/**/export","/**/import");  //排除登录注册导入导出

    }

    //注入到bean 不然可能拿不到userService
    @Bean
     public  JWTInterceptor jwtInterceptor(){
        return new JWTInterceptor();
     }
}
里面有些是我自己定义的类,如userDto,userServiceImpl,异常处理类ServiceException,也有使用到hutool,需要导入依赖。
 
 


                
        
        
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-15 11:30:57  更:2022-05-15 11:31:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 14:02:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码