JWT令牌详解

定义--看看就行了:=================================

JWT(JSON Web Token) 是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象的形式安全地传输信息。

JWT 由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

  1. Header:包含令牌类型(即 JWT)和签名算法(如 HMAC SHA256 或 RSA)。
  2. Payload:可以在里面存信息
  3. Signature:简单理解就是密码

使用场景:========================================

1.登录验证:

        不做登陆验证的话,黑子如果知道你的url和请求参数,就可以直接通过浏览器或者postman之类的工具请求你的服务端,很危险,所以要验证这个请求是不是合法的。

流程:

生成令牌:登录时login请求是直接放进来的,然后用户名密码正确就可以生成令牌了,上面不是说可以在payload中存信息吗,生成令牌的过程中就可以将用户的信息存进去,爱放不放,放进去肯定有用。

存储令牌:令牌就是一字符串,没那么高大尚。login请求时后端将生成的令牌返回给前端,然后前端可以保存在浏览器的local storage中

携带令牌:以后在前端发起请求时都要将令牌作为请求头传给后端,可以在前端使用拦截器实现

验证令牌:后端在接收除login外的请求,都要先验证令牌,合法了我才让你请求我的服务(请求到后端的controller)

2.传递用户信息:

        先不细说

实现:===========================================

1.引入jjwt依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2.创建jwt工具类--创不创其实无所谓,主要是更方便后面使用,为了优雅二字

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;

import java.util.Date;

public class JwtUtil {
    private static final String SECRET_KEY = "yourSecretKey"; // 密钥--创建、解析令牌时要用

    //生成jwt令牌
    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 1 天有效期
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)  //签名算法
                .compact();
    }
    //解析jwt令牌
    public static boolean validateToken(String token) {
        try {
            Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token);
            return true;
        } catch (SignatureException | ExpiredJwtException | MalformedJwtException e) {
            return false;
        }
    }
}

3.配置拦截器拦截用户请求进行jwt验证(使用过滤器也可以)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

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

@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取到请求头中的令牌
        String authorizationHeader = request.getHeader("Authorization");

        //校验令牌是否合法
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            String token = authorizationHeader.substring(7);
            if (jwtUtil.validateToken(token)) {
                return true;
            }
        }
        //返回不合法信息
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid or missing Authorization header");
        return false;
    }
}

4.注册并配置拦截器

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

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login"); // 排除登录路径
    }
}

5.在后端登录控制器中生成令牌并返回给前端

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/login")
    public Map<String, String> login(@RequestBody AuthRequest authRequest) {
        try {
            //验证用户名密码是否正确
            userMapper.......
            //正确后进行下面步骤,否则直接返回
           
            //生成令牌-username作为数据载荷部分
            String token = jwtUtil.generateToken(authRequest.getUsername());
            //将生成的令牌返回给前端
            Map<String, String> response = new HashMap<>();
            response.put("token", token);
            return response;
        } catch (AuthenticationException e) {
            throw new RuntimeException("Invalid login credentials");
        }
    }
}

class AuthRequest {
    private String username;
    private String password;

    // getters and setters
}

回顾整个流程:=====================================

用户首先进行登录==》

        请求到后端controller==》

                (用户名密码正确)生成令牌返回给前端==》

                        前端保存令牌并在以后每次请求中携带令牌

用户发起其他请求(请求头中携带了令牌)==》

        后端拦截器拦截用户请求==》

                解析请求中令牌是否合法==》

                        合法放行,不合法拒绝访问

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值