Spring Boot使用JWT进行身份验证

1.JWT

JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间作为令牌传递信息。这个令牌可以用于认证和授权,也可以用于在各方之间传递信息。
一个JWT主要包括三个部分:头部(Header)、负载(Payload)和签名(Signature)。
头部(Header):这是一个JSON对象,描述了将要被签名的数据使用的算法类型,比如 "HS256" 代表 HMAC SHA-256 签名算法。
负载(Payload):这是一个JSON对象,包含了要发送的数据。这些数据可以是用户ID、角色、用户名等。
签名(Signature):这是对头部和负载进行签名后的结果,用来保证头部和负载的完整性和真实性。签名是通过对头部和负载进行散列,然后用一个密钥生成一个签名值。
使用base64进行编码:

Base64URL(header).Base64URL(payload).Base64URL(signature)

2.使用思路介绍

用户登录之后生成JWT令牌,并将令牌存到redis以及发送给用户,用户每次请求都包含JWT令牌服务器进行验证。

3.使用代码

3.1 安装环境

需要在springboot中安装包:

implementation 'com.auth0:java-jwt:4.4.0'
implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.5.14'

3.2 JWT令牌生成及校验

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.Map;

public class JwtUtils {
    //加密密钥
    public static final  String KEY="123456";
    //生成JWT令牌
    public static  String createJWT(Map<String, Object> json){
        return  JWT.create()
                .withClaim("claims",json)
                .withExpiresAt(new Date(System.currentTimeMillis()+1000*3600*12))
                .sign(Algorithm.HMAC256(KEY));
    }

    //验证JWT令牌
    public static Map<String,Object> verifyJWT(String token){
        return JWT.require(Algorithm.HMAC256(KEY)).build()
                .verify(token)
                .getClaim("claims")
                .asMap();

    }
}

3.3 全局请求进行验证

登录拦截器(Interceptor):

import com.example.videoplay.utils.JwtUtils;
import com.example.videoplay.utils.Result;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        String url = req.getRequestURL().toString();
        System.out.println("请求的url: "+url);
        if(url.contains("login")||url.contains("register")){
            System.out.println("登录操作, 放行...");
            return true;
        }
        String jwt = req.getHeader("token");
        //从redis获取相同的token
        ValueOperations<String,String> operations=stringRedisTemplate.opsForValue();
        if(!StringUtils.hasLength(jwt)){
            System.out.println("请求头token为空,返回未登录的信息");
            Result error = new Result().error("NOT_LOGIN");
            String notLogin = error.toString();
            resp.getWriter().write(notLogin);
            return false;
        }

        //先从redis中查看是否有该密钥,再尝试进行解密
        try {
            String redisToken=operations.get(jwt);
            if(redisToken==null){
                throw new RuntimeException();
            }
            JwtUtils.verifyJWT(jwt);
        } catch (Exception e) {//jwt解析失败
            e.printStackTrace();
            System.out.println("解析令牌失败, 返回未登录错误信息");
            Result error = new Result().error("NOT_LOGIN");
            //手动转换 对象--json --------> 阿里巴巴fastJSON
            String notLogin = error.toString();
            resp.getWriter().write(notLogin);
            return false;
        }
        System.out.println("令牌合法, 放行");
        return true;
    }

    @Override //目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ...");
    }

    @Override //视图渲染完毕后运行, 最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

3.4 redis数据存取

存数据:

@Autowired
private StringRedisTemplate stringRedisTemplate;

ValueOperations<String,String> operations=stringRedisTemplate.opsForValue();
operations.set(token,token,12, TimeUnit.HOURS);

取数据:

String redisToken=operations.get(jwt);

删除数据:

operations.getOperations().delete(token);
暂无评论

发送评论 编辑评论


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