当前位置:首页 » 《随便一记》 » 正文

什么是JWT(Json-Web-Token)?JWT的用途和优势是什么?讲解+实战,一篇文章学会JWT怎么用!

13 人参与  2024年02月23日 09:16  分类 : 《随便一记》  评论

点击全文阅读


1、什么是JWT

最近刚刚启动搭建一个会员支付系统的项目,单点登录用到JWT来认证,借此机会来谈一谈JWT的相关知识,后续也会分享项目中的相关技术点,大家点赞关注哦~~~

1.1、JWT的介绍

官方解释:JSON Web Token (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

简单来说,JWT就是用来判断某种信息是否可以被信任的一种签名json

1.2、JWT的使用场景

身份验证(Authentication):JWT 可以被用作用户登录的身份验证凭证。当用户成功登录后,服务端可以生成一个包含用户信息的 JWT,并将其返回给客户端。以后,客户端在每次请求时都会携带这个 JWT,服务端通过验证 JWT 的签名来确认用户的身份。

授权(Authorization):在用户登录后,服务端可以生成包含用户角色、权限等信息的 JWT,并在用户每次请求时进行验证。通过解析 JWT 中的声明信息,服务端可以判断用户是否有权限执行特定的操作或访问特定的资源。

信息交换(Information Exchange):由于 JWT 的声明信息可以被加密,因此可以安全地在用户和服务器之间传递信息。这在分布式系统中非常有用,因为可以确保信息在各个环节中的安全传递。

单点登录(Single Sign-On):JWT 可以被用于支持单点登录,使得用户在多个应用之间只需要登录一次即可使用多个应用,从而提高用户体验。

1.3、JWT的优势

无状态:JWT 的验证是基于密钥的,因此它不需要在服务端存储用户信息。这使得 JWT 可以作为一种无状态的身份认证机制。

跨语言支持:JWT 的标准化和简单性质使得它可以在多种语言和平台之间使用。

安全性高:由于 JWT 的载荷可以进行加密处理,因此 JWT 能够保证数据的安全传输。同时,JWT 的签名机制也能够保证数据的完整性和真实性。

2、JWT的结构

JWT由Header+Payload+Signature三部分组成 

Header

JWT 的头部通常由两部分组成,分别是令牌类型(typ)和加密算法(alg)。一般情况下,头部会采用 Base64 编码。 

{  "alg": "HS256",  "typ": "JWT"}

Payload

JWT 的载荷也称为声明信息,包含了一些有关实体(通常是用户)的信息以及其他元数据。通常包括以下几种声明:

Registered Claims:这些声明是预定义的,包括 iss(发行者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(生效时间)、iat(发布时间)和 jti(JWT ID)等。

Public Claims:这些声明可以自定义,但需要注意避免与注册声明的名称冲突。

Private Claims:这些声明是保留给特定的应用程序使用的,不会与其他应用程序冲突。

注意:Payload中一定不要存放敏感或重要信息,如密码等

{  "sub": "666666",  "name": "warriors",  "admin": true}

 Signature

JWT 的签名是由头部、载荷和密钥共同生成的。它用于验证 JWT 的真实性和完整性。一般情况下,签名也会采用 Base64 编码。
例如,如果要使用 HMAC SHA256 算法,将按以下方式创建签名:

HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)

3、SpringMVC架构中的JWT使用示例

3.1、引入Maven依赖

<dependency>   <groupId>io.jsonwebtoken</groupId>   <artifactId>jjwt-api</artifactId>   <version>0.11.5</version></dependency><dependency>   <groupId>io.jsonwebtoken</groupId>   <artifactId>jjwt-impl</artifactId>   <version>0.11.5</version>   <scope>runtime</scope></dependency><dependency>   <groupId>io.jsonwebtoken</groupId>   <artifactId>jjwt-jackson</artifactId>   <version>0.11.5</version>   <scope>runtime</scope></dependency>

3.2 、编写JWT工具类,实现JWT生成,JWT校验等功能
 

public class JWTUtil {    // JWT过期时间    public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;    // JWT_KEY为服务器私钥,注意保密    public static final String JWT_KEY = "aBcDeFgHdkfajdja50490fjaifeja4ief";    public static String getUUID() {        return UUID.randomUUID().toString().replaceAll("-", "");    }    /**     * 生成JWT     * @param subject 用户唯一标识ID     * @return     */    public static String createJWT(String subject) {        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());        return builder.compact();    }    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {        // 自行选择加密算法        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;        SecretKey secretKey = generalKey();        long nowMillis = System.currentTimeMillis();        Date now = new Date(nowMillis);        if (ttlMillis == null) {            ttlMillis = JWTUtil.JWT_TTL;        }        long expMillis = nowMillis + ttlMillis;        Date expDate = new Date(expMillis);        return Jwts.builder()                .setId(uuid)                .setSubject(subject)                .setIssuer("sg")                .setIssuedAt(now)                .signWith(signatureAlgorithm, secretKey)                .setExpiration(expDate);    }    public static SecretKey generalKey() {        byte[] encodeKey = Base64.getDecoder().decode(JWTUtil.JWT_KEY);        return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");    }    /**     * 校验JWT     */    public static Claims parseJWT(String jwt) throws Exception {        SecretKey secretKey = generalKey();        return Jwts.parserBuilder()                .setSigningKey(secretKey)                .build()                .parseClaimsJws(jwt)                .getBody();    }}

3.3、自定义拦截器

public class JWTIntercepter implements HandlerInterceptor {    public static final Logger LOGGER = LoggerFactory.getLogger(JWTIntercepter.class);    /**     * 添加用户身份认证     * @param request     * @param response     * @param handler     * @return     * @throws Exception     */    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        String jwttoken = HttpRequestUtil.getCookieValue(request, "jwt_token");        if (jwttoken == null || jwttoken.isEmpty()) {            return false;        }        try {            Claims claims = JWTUtil.parseJWT(jwttoken);        } catch (JwtException e) {            LOGGER.info("JWT解析异常:" + e.getMessage());            return false;        }        response.sendError(ResponseEnum.USER_UNAUTHORIZED.getCode(),                ResponseEnum.USER_UNAUTHORIZED.getMessage());        return false;    }}

3.4、配置拦截器到拦截器链中

@Configurationpublic class WebMVCConfig implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        JWTIntercepter jwtIntercepter = new JWTIntercepter();        registry.addInterceptor(jwtIntercepter)                .addPathPatterns("/**")                //注意:登陆和注册请求放行                .excludePathPatterns("/user/login", "/user/register");    }}

至此,jwt的配置已全部完成~~~ 

大家有任何问题,欢迎在评论区留言,看到会第一时间答复,如内容技术上存在问题,请大胆指正!!!
 


点击全文阅读


本文链接:http://zhangshiyu.com/post/69533.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1