Java中JWT令牌实现登录验证

 更新时间:2024年12月30日 10:12:09   作者:水冠7  
本文主要介绍了JWT令牌在Java中实现登录验证的方法,JWT是一种自我包含的、无状态的认证机制,可以用来在客户端和服务器之间传递安全可靠的信息,感兴趣的可以了解一下

1.实现登录验证的引出

传统思路下:

  • 登录页面把用户名和密码交给服务器。
  • 服务器验证用户名和密码是否正确,并返回校验结果给后端。
  • 如果密码正确,就会在服务器创建Session,通过Cookie把sessionId返回给客户端。

原因

但是在集群环境下,无法直接使用Session。因为如果只部署在一台机器时,容易发生单点故障(一旦这台服务器挂了,整个应用就无法访问),所以通常情况下,一个Web应用会部署在多个服务器上,通过Nginx等进行负载均衡。此时,来自一个用户的请求就会分发到不同的服务器上

在这里插入图片描述

  • 使用Session时:

    用户登录: 用户登录请求,经过负载均衡发送给服务器1,服务器1进行用户名和密码验证,验证成功后,把Session存在了服务器1上。

    查询操作:用户登录之后,携带Cookie(里面带有SessionId)继续执行查询操作,假如进行查询博客列表,此时请求经过负载均衡发到服务器2上,服务器2会先通过SessionId验证用户是否登录,此时第二台机器上没有该用户的Session,即出现查询不了的问题。

在这里插入图片描述

2.JWT令牌

JWT全称:JSON Web Token,用于客户端和服务器之间传递安全可靠的信息,本质是一个token,也叫token,令牌的本质就是一个字符串。相当于现在人们的身份证,出门在外验证身份的时候,拿出身份证即可。

2.1 使用JWT令牌时

  • 用户登录 : 用户登录请求,经过负载均衡,把请求发给服务器1,服务器1进行账号密码验证,验证成功之后,生成一个令牌,并返回给客户端。
  • 客户端收到令牌时,把令牌存储起来,可以存储在Cookie中,也可以存储在其它的存储空间,典型的如(localStorage)
  • 查询操作 用户登录之后,携带令牌继续执行查询操作,假如查询博客列表,此时请求经过负载均衡发到服务器2,服务器2先进行权限验证操作。服务器验证令牌是否有效,如果有效,说明用户已经执行了登录操作,如果无效,说明用户之前未执行登录操作。

在这里插入图片描述

2.2 令牌的组成

令牌官网所示,token,本质上一个字符串中间使用 符号 点 . 来分割,令牌由三部分组成,header、payload和verify signature

在这里插入图片描述

  • 第一部分:Header(头),令牌的类型和使用的签名算法,如"alg": “HS256(哈希算法)”, “typ”: “JWT”。

  • 第二部分:Payload(负载),存放一些有效的信息(自定义信息,默认信息)如{“id”:“1”,“username”:“zhangsan”},还存在JWT提供的现场字段,如过期时间戳等。

  • 第三部分:Signature(签名),防止token被篡改,确保安全性

    签名的目的就是为了防止token被篡改,而正因为token最后一个部分签名存在,
    所以整个token是非常安全可靠的,一旦token当中的任何一部分被修改,
    整个token在校验的时候都会失败。 
    

3. JWT令牌(token)生成和校验

3.1 引入JWT令牌的依赖

  • 在pom.xml文件中引入依赖
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt-api</artifactId>
			<version>0.11.5</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
		<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> <!-- or jjwt-gson if Gson is
preferred -->
			<version>0.11.5</version>
			<scope>runtime</scope>
		</dependency>

3.2 使用Jar包中提供的API来实现JWT令牌的生成和校验

  • 生成token之后,获取token进行解析,创建解释器,设置签名密钥,如果解析token的claims内容不为null,说明校验成功,否则失败。
package com.example.blog.utils;

import com.example.blog.constant.Constants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtUtils {
    // JWT过期时间
    public static final long JWT_EXPIRATION = 60*60*60*1000;
    // 生成key
    private static final String secretStr = "DuJXRS2W3AJHqyFhAplBmsPNawnEdFYFNmlNdMbyU9w=";
    private static final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretStr));

    /**
     *  生成token
     */
    public static String genJwtToken(Map<String,Object> claim) {
        String token = Jwts.builder().setClaims(claim)
                .setExpiration(new Date(System.currentTimeMillis()+JWT_EXPIRATION))
                .signWith(key)
                .compact();
        return token;
    }


    /**
     *  校验token
     *  Claims 为空,表示jwt校验失败
     *
     */
    public static Claims parseToken(String token) {
        // 创建解析器,设置签名密钥
        JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();
        Claims claims = null;
        try {
            // 解析token
            claims = build.parseClaimsJws(token).getBody();
        }catch (Exception e){
            log.error("解析token失败,token:{}",token);
            return null;
        }
        return claims;
    }
}

3.3 使用JWT令牌验证登录

在这里插入图片描述

3.4 令牌的优缺点

  • 优点:
    • 解决了集群环境下认证的问题
    • 不需要在服务器端存储,从而减轻了服务器的存储压力
  • 缺点:
    • 需要自己实现令牌的生成、传递、校验

到此这篇关于Java中JWT令牌实现登录验证的文章就介绍到这了,更多相关Java JWT令牌登录验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • java接入创蓝253短信验证码的实例讲解

    java接入创蓝253短信验证码的实例讲解

    下面小编就为大家分享一篇java接入创蓝253短信验证码的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Java中读取配置文件的示例详解

    Java中读取配置文件的示例详解

    这篇文章主要为大家详细介绍了Java中读取配置文件properties的相关方法,文中的示例代码简洁易懂,感兴趣的小伙伴快跟随小编一起学习一下吧
    2023-10-10
  • Springboot整合Freemarker的实现详细过程

    Springboot整合Freemarker的实现详细过程

    这篇文章主要介绍了Springboot整合Freemarker的实现详细过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SpringBoot集成quartz实现定时任务详解

    SpringBoot集成quartz实现定时任务详解

    最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式。本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数据库的分布式任务管理和控制job生命周期
    2022-08-08
  • springboot修改端口号的实现方式

    springboot修改端口号的实现方式

    文章介绍了如何在Spring Boot项目中修改默认端口号,通过在`application.properties`或`application.yml`文件中添加`server.port=端口号`来实现
    2026-01-01
  • Java将CSV的数据发送到kafka的示例

    Java将CSV的数据发送到kafka的示例

    这篇文章主要介绍了Java将CSV的数据发送到kafka得示例,帮助大家更好得理解和使用Java,感兴趣的朋友可以了解下
    2020-11-11
  • 详解Java线程池和Executor原理的分析

    详解Java线程池和Executor原理的分析

    这篇文章主要介绍了详解Java线程池和Executor原理的分析的相关资料,这里提供实例及分析原理帮助大家理解这部分知识,需要的朋友可以参考下
    2017-07-07
  • SpringBoot和Tomcat的关系解读

    SpringBoot和Tomcat的关系解读

    这篇文章主要介绍了SpringBoot和Tomcat的关系,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • SystemServer进程启动过程解析

    SystemServer进程启动过程解析

    这篇文章主要为大家介绍了SystemServer进程启动过程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Java基于ReadWriteLock实现锁的应用

    Java基于ReadWriteLock实现锁的应用

    这篇文章主要介绍了Java基于ReadWriteLock实现锁的应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10

最新评论