Jwt

说明

观看B站视频整理的笔记。https://www.bilibili.com/video/BV1i54y1m7cP?from=search&seid=11707701064126824134

JTW的简介和传统认证流程对比

什么是JWT?

JWT官网地址:https://jwt.io/introduction
JWT的全称:JSON Web Token,即json格式网站令牌

Jwt的作用

1.授权

这是使用JWt的最常见的方案,一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。

2.信息交换

JWT是在各方之间安全地传输信息的好方法。因为可以对JWt进行签名(例如:使用公钥/私钥对),所以可以确保发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此还可以验证内容是否遭到篡改。

为什么使用JWT

基于传统的Session认证


基于JWT认证


JWT的结构



使用JWT




封装工具类


springboot整合JWT

整体流程:前台发送用户名、密码---->后台验证是否成功,成功则生成Token返回令牌。
注意:令牌的盐值必须4个及以上字符否则会出现如下错误:

jwt工具类

package com.example.jwt.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @Author czf
 * @Date 2021/3/23
 * @ClassName: JwtUtil
 * @Description: jwt的工具类
 * @Version 1.0
 */
@Component
public class JwtUtil {
    // 盐值
    private static final String KEY = "czfs";
    //一天时间失效
    private static final String ttl = "86400000";

    /**
     * 签发 生成 token
     */
    public static String createJWT(String userId, String userName) {
        long now = System.currentTimeMillis();
        long time = Long.parseLong(ttl);
        long exp = now + time;
        //1.创建jwtBuilder
        JwtBuilder jwtBuilder = Jwts.builder().setId(userId)
                .setSubject(userName).setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, KEY);
        //时间设置
        if (time > 0) {
            jwtBuilder.setExpiration(new Date(exp));
        }
        return jwtBuilder.compact();
    }

    /**
     * 解析 token
     */
    public static Claims parserJWT(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(KEY)
                    .parseClaimsJws(token).getBody();
        } catch (Exception ignored) {
        }
        return claims;
    }

}

拦截器

package com.example.jwt.configure;
import com.alibaba.fastjson.JSONObject;
import com.example.jwt.util.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author czf
 * @Date 2021/3/23
 * @ClassName: JwtInterceptor
 * @Description: 对请求进行token的验签
 * @Version 1.0
 */
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        Claims claims = JwtUtil.parserJWT(token);
        if (claims == null){
            log.info("token不正确!");
            Map<String, Object> map = new HashMap<>();
            map.put("msg", "token不正确");
            // 将map转换为json ,response底层有jackson
         /*   String jsonString = new ObjectMapper().writeValueAsString(map);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().println(jsonString);*/
            // fastJson将map转换json字符串
            JSONObject jsonObject = new JSONObject(map);
            String jsonString = jsonObject.toString();
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().println(jsonString);
            return false;
        }
        return true;
    }
}

注册拦截器

package com.example.jwt.configure;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author czf
 * @Date 2021/3/23
 * @ClassName: InterceptorConfig
 * @Description: 拦截器的配置信息
 * @Version 1.0
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 除了登录请求不需要验签,其它请求都需要
        registry.addInterceptor(new JwtInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");
    }
}

基类控制层

package com.example.jwt.controller;

import com.example.jwt.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.web.bind.annotation.ModelAttribute;

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

/**
 * @Author czf
 * @Date 2021/3/23
 * @ClassName: BaseController
 * @Description: 抽取控制层的公共代码
 * @Version 1.0
 */
public class BaseController {
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected String userName;
    protected String token;
    protected String userId;

    @ModelAttribute
    public void setResAnReq(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
        try {
            this.token = this.request.getHeader("token");
            Claims claims = JwtUtil.parserJWT(token);
            this.userName = claims.getSubject();
            this.userId = claims.getId();
        } catch (Exception e) {
            System.out.println("令牌不正确!");
            throw e;
        }
    }

    public String getUserName(){
        return this.userName;
    }
}

@ModelAttribute注解的作用

被@ModelAttribute注释的方法会在此controller每个方法执行前被执行。所以setResAnReq方法会在这个controller中优先执行。

controller

package com.example.jwt.controller;

import com.example.jwt.modol.User;
import com.example.jwt.service.impl.UserServiceImpl;
import com.example.jwt.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * @Author czf
 * @Date 2021/3/23
 * @ClassName: userController
 * @Description: 用户控制层
 * @Version 1.0
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController extends BaseController{
    @Resource
    UserServiceImpl userServiceImpl;

    @PostMapping("/login")
    public String login(@RequestParam String userName,@RequestParam String password){
        User user1 = userServiceImpl.findUser(userName,password);
        if (null !=user1){
            String token = JwtUtil.createJWT("" + user1.getId(), user1.getUserName());
            return token;
        }else {
            return "fail";
        }
    }

    @GetMapping("/test")
    public String test(){
        log.info("用户名:{}" ,getUserName());
        return "test";
    }
}

代码托管:https://gitee.com/czf96/jwt

JWt与sesion的对比

JWt是存储在客户端中的,而sesion存储在服务器内存中。如果将后台关闭过,sesion就失效(丢失)了必须重新登录验证。JWt只要token没有过期(无论后台是否关闭过),都可以直接使用,后台对token进行验证,验证(验证token是否是自己创建的)通过就可以访问控制层了。

posted @   C紫枫  阅读(572)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示