欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JWT - 通过Axios拦截器完成Token转发实现单点登录

程序员文章站 2024-03-19 15:24:28
...

前端部分

需要将token字符串用户信息存入的Cookie中,因此需要引入js-cookie。前端采用axios发送请求,所以还需要引入axios

1、封装axios

创建一个request.js文件,用来封装axios

import axios from 'axios';  // 引入axios
import cookie from 'js-cookie';  // 引入js-cookie

// 创建axios实例
const service = axios.create({
	baseURL:'http://localhost:9000',   // 请求地址,可以使用nginx代理
	timeout:20000					   // 请求超时时间
});

// 配置request拦截器
service.interceptors.request.use(
	config => {
	    // 如果Cookie中存在这个token,就在header中设置这个token
	    // 这样token就可以跨域转发
		if(cookie.get('user_token')){
			config.headers['token'] = cookie.get('user_token');
		}
		return config;
	},
	err => {  // 出错调用
		return Promise.reject(err);
	}
)
export default service;

2、定制API - login.js

定制登录的方法。

import request from '@/utils/request';  // 引入request.js
export default {
    /**
     * 登录的方法
     * @param userInfo 用户登录信息
     */
	submitLogin(userInfo){
		return request({
			// 登录的请求地址,完整即http://localhost:9000/user/login
			url:'/user/login',  
			method:'post',   // 请求方式
			data:userInfo    // 请求信息
		});
	}
}

3、完成登录 - 基于Vue和Axios发送请求

import cookie from 'js-cookie'
import loginApi from '@/api/login'

export default{
	data(){
		return {
			user:{
				mobile:'',    // 手机/账号
				password:'',  // 密码
			},
			loginInfo:{},     // 登录用户信息
		}
	},
	methods:{
		/**
		 * 登录按钮调用的方法
		 */
		submitLogin(){
			/**
			 * 调用登录API
			 */
			loginApi.submitLogin(this.user)
				.then(response => {
				    // 将服务端传过来的token字符串存入cookie
					cookie.set('user_token',response.data.data.token,{domain:'localhsot'});
					// 这里就可以调用方法去获取用户信息并存入Cookie了
					// 方法就不再定义了,直接使用,定义方式与前面一致
					// 因为在request.js中制定了拦截器,会检查token是否存在,存在就跟着header信息一起被传走
					loginApi.getLoginUserInfo()
						.then(response => {
							this.loginInfo = response.data.data.userInfo;
							// 将获取到的用户信息存入到cookie中,其他页面从cookie中取
							cookie.set('user_info',this.loginInfo,{domain:'localhost'});
							// 跳转到首页 - 也可以使用路由跳转
							// 首页就可以从cookie中获取了
							window.location.href = "/";
						})
				})
		}
	}
}

4、登录成功,信息获取

在cookie中获取信息,通过JSON.parse方法将其转换为JSON对象。

后端部分

1、要使用JWT,需要引入JWT的依赖

<!-- JWT-->
<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt</artifactId>
	<version>0.7.0</version>
</dependency>

2、创建JWT帮助类

public class JwtUtils {

    // 常量
    public static final long EXPIRE = 1000 * 60 * 60 * 24; // token过期时间
    public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; // 秘钥

    // 生成token字符串的方法
    public static String getJwtToken(String id, String nickname){
        String JwtToken = Jwts.builder()
                // 头信息
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                .setSubject("guli-user")   // 分类
                // 设置过期时间
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                // 设置Token主体部分,存储用户信息
                .claim("id", id)
                .claim("nickname", nickname)


                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }

    /**
     * 判断token是否存在与有效
     * @param jwtToken
     * @return
     */
    public static boolean checkToken(String jwtToken) {
        if(StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判断token是否存在与有效
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据token字符串获取id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }
}

3、验证用户登录成功之后生成Token字符串

String jwtToken = JwtUtils.getJwtToken(user.getId(),user.getNickname());

4、根据token信息获取用户信息

前面前端部分说了,每次请求的时候,都会将token信息放入header,这样就可以跨域(cookie无法跨域)。
要获取用户信息,则需要通过这个token信息来确定,使用jwt帮助类中的getMemberIdByJwtToken方法来获取。

    /**
     * 根据token字符串获取id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }

获取到id,我们就可以通过这个id去获取用户信息。

@GetMapping("/getUserInfo")
public R getMemberInfo(HttpServletRequest request){
	String userId = JwtUtils.getMemberIdByJwtToken(request);
	User user= userService.getById(userId);
	return R.ok().data("userInfo",user);
}

到此为止,完成了一个简单的token跨域验证。