token的登陆校验小结

本文总结了使用token进行登录拦截的思路,涉及技术包括token、Redis和Jackson。在登录过程中,若出现异常,会导致前端跨域问题,因为自定义拦截器会先于CORS过滤器执行。解决这个问题的方法是妥善处理异常,确保跨域处理正常进行。
摘要由CSDN通过智能技术生成

关于token做登陆拦截的思路整理:

使用到的技术:token,redis,jackson

maven加载token
编写token的生成和解析静态工具类

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;


@Component
@Slf4j
public class TokenUtils {

    private static final String secret="miyao";

/**
 *依赖
 <dependency>
 <groupId>com.auth0</groupId>
 <artifactId>java-jwt</artifactId>
 <version>3.15.0</version>
 </dependency>
 */
    
    
    /**
     * 生成token
     * @param uuid
     * @return
     */
    public String createToken(String uuid){
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            String token = JWT.create()
                    .withIssuer("qianfaren")
                    .withSubject("token")
                    .withClaim("uuid",uuid)
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException exception){
            //Invalid Signing configuration / Couldn't convert Claims.
            log.error("token生成失败");
        }
        return "";
    }
    

    /**
     * 解析token
     * @param token
     * @return
     */
    public DecodedJWT getJwt(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("qianfaren")
                    .build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(token);
            return jwt;
        } catch (JWTVerificationException exception){
            //Invalid signature/claims
            log.error("token解析错误");
        }

        return null;
    }


    /**
     * 获取uuid
     * @param token
     * @return
     */
    public String UUidGetByJwt(String token){
        DecodedJWT jwt = getJwt(token);
        if(jwt!=null){
            return jwt.getClaim("uuid").asString();
        }
        return null;
    }

    /**
     * 从请求中获取uuid
     * @param httpServletRequest
     * @return
     */
    public String getUUidFromToken(HttpServletRequest httpServletRequest){
        String authorization = httpServletRequest.getHeader("Authorization");
        String s = authorization.split(" ")[1];
        DecodedJWT jwt = getJwt(s);
        String uuid = jwt.getClaim("uuid").asString();
        return uuid;
    }


}


登陆步骤:

前端发送登录请求之后 
-> 验证登陆成功
-> 把验证查找到的用户信息使用jackson转为字符串
-> 以生成的uuid为key,用户字符串为value储存在redis中 
-> 给前端返回生成的token -> 前端储存到本地 :使用cookie存储,有vue-cookie和js-cookie,百度即可
	验证步骤: 前端每次发送请求都要携带之前储存	在本地的token(方法见AXIOS统一文档) 
	存在请求头中发送到后端 
/*
* 封装axios
* */
import axios from "axios";
import { Notification } from 'element-ui';
//创建
const instance = axios.create({
    baseURL: 'http://localhost:10001/',//统一请求
    timeout: 3000,
});
// Add a request interceptor请求之前
instance.interceptors.request.use(function (config) {
    // Do something before request is sent
	    config.headers.Authorization存的值key,后台根据这个拿="Bearer "+从cookie获取token
    return config;
}, function (error) {
    // Do something with request error
    return Promise.reject(error);
});
//请求之后
instance.interceptors.response.use(function (response) {
    let {status, message, data} = response.data
    if(status==20000){
        return data
    }else {
        Notification({
            title: '警告',
            message: message,
            type: 'warning'
        });
        return Promise.reject(false);
    }
}, function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    return Promise.reject(error);
});

export default instance;
-> 后端配置拦截器,拦截除登陆,首页,获取验证的其他请求 
-> (此时会出现一个问题:我们只能在拦截器中获取请求头中的token,
		如果想要在其他方法中获取, 需要每个方法中写入HttpServletRquest,太麻烦,
		我们需要一个工具类,可以随时获取全局的HttpServletRquest,
		以便于我们解析其中携带的请求头中的token)
package com.sm.qy28.contorller.lanjieqi;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class SevletUtils {

    /**
     * 获取全局的Request
     * @return
     */
    public static HttpServletRequest getRequest(){
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes.getRequest();

    }

}
编写解析token静态方法,获取Rquest中请求头中携带的token,解析出uuid,
再用UUid为key查询 Redis中储存的用户信息字符串 -> 查询成功就代表为登录状态 
如果查询不成功,或解析就不成功,不应该在拦截器中返回false,而是应该抛出异常,并处理

此时,如果抛了异常,前端就会出现跨域问题,因为如果抛异常,那么你在spring里配置的跨域处理cores就没有作用,因为我们自定义的拦截器会在cores过滤器之前执行,如果我们的拦截器直接抛异常,那么就不会进入cores过滤器,自然就不会处理跨域问题,解决方案见跨域处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值