Java中JWT技术解析与实践:安全高效的身份认证

这篇具有很好参考价值的文章主要介绍了Java中JWT技术解析与实践:安全高效的身份认证。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

jwt常见问题回复&简介

  1. 什么是JWT(JSON Web Token)?
    JWT是一种用于身份验证和授权的开放标准(RFC 7519),它是基于JSON格式的轻量级安全令牌。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。通常,JWT被用于在不同的系统之间传递安全性的声明信息,以便用户在跨域应用中进行身份验证。

  2. JWT有什么好处,能干啥?
    JWT的主要优点包括:

  • 轻量级:JWT是基于JSON格式的,相比于传统的XML格式,它更加轻巧且易于解析。
  • 自包含:JWT中包含了用户的一些声明信息,因此无需查询数据库来验证用户身份,有效降低了服务器的负担。
  • 无状态性:JWT本身是无状态的,所有的信息都被包含在令牌中,服务器端无需保存任何状态信息,使得系统易于扩展和维护。
  • 安全性:JWT中使用签名进行验证,防止数据被篡改,确保了数据的完整性和安全性。

JWT能够实现的功能包括:

  • 用户认证:JWT可以用于用户身份验证,客户端通过携带有效的JWT令牌来请求受限资源。
  • 单点登录(SSO):用户在一个应用登录后,可以获取JWT令牌,然后在其他相互信任的应用中使用该令牌来免登录。
  • 授权信息传递:JWT中的载荷可以包含用户的角色、权限等信息,服务器可以根据这些信息做出授权决策(私密信息不要使用JWT 可以被人解析)。
  1. JWT的组成:
    JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
  • 头部(Header):通常由两部分组成,令牌类型(typ)和使用的签名算法(alg)。示例:{"alg": "HS256", "typ": "JWT"}
  • 载荷(Payload):包含用户的声明信息,例如过期时间用户ID、角色、权限等。可以自定义其他声明信息。示例:{"sub": "1234567890", "name": "John Doe", "admin": true}
  • 签名(Signature):通过对头部和载荷进行签名,保证数据的完整性和安全性。签名的生成通常使用密钥进行加密,只有持有密钥的服务器才能验证签名的有效性。
  1. 如何使用JWT?
    使用JWT通常包括以下步骤:
  • 用户登录:用户提供用户名和密码进行登录验证。
  • 服务器验证:服务器验证用户提供的信息是否正确,并生成JWT令牌。
  • 令牌传递:服务器将JWT令牌发送回客户端。
  • 客户端使用:客户端在后续请求中携带JWT令牌,发送给服务器进行身份验证和授权。
  1. 系统中的JWT是如何使用的,在什么时候使用的?
    在一个系统中,JWT通常用于实现用户身份验证和授权。当用户登录成功后,服务器会生成一个JWT令牌并发送给客户端,客户端保存该令牌,并在后续的请求中将令牌添加到请求头或请求参数中。服务器在收到请求时,会解析JWT令牌并验证其合法性和有效性,从而判断用户是否已经登录以及是否有权限访问请求的资源。

    JWT的使用可以简化系统的身份验证和授权流程,提高系统的安全性和性能。同时,由于JWT本身是无状态的,不需要在服务器端保存会话信息,使得系统更易于扩展和维护。引入jwt,并使用生成token

使用步骤

当使用JWT进行用户身份验证和授权时,通常包含以下步骤:

  1. 用户登录认证:

    • 用户提供用户名和密码进行登录。
    • 服务器接收用户提交的用户名和密码,通过UserService类中的authenticateUser方法验证用户名和密码是否正确。
    • 如果用户名和密码验证通过,认为用户登录成功,可以继续下一步生成JWT令牌。
  2. 生成JWT令牌:

    • 在登录成功后,服务器使用JwtUtils工具类中的generateJwtToken方法生成JWT令牌。
    • generateJwtToken方法接收三个参数:
      • subject:即载荷(Payload)中的"sub"字段,通常用于标识用户的唯一标识,例如用户ID、用户名等。
      • expirationMillis:令牌的有效期,以毫秒为单位。令牌过期后将无效,需要重新登录获取新的令牌。
      • SECRET_KEY:用于签名的密钥,确保密钥保密,不要泄露给他人。
    • generateJwtToken方法会使用Jwts类的builder方法构建JWT令牌,并设置令牌的头部(Header)、载荷(Payload)、过期时间(Expiration)等信息。
    • 最后,使用指定的签名算法(此处使用HS256)对令牌进行签名,生成签名(Signature)部分,得到最终的JWT令牌。
  3. 返回JWT令牌:

    • 服务器将生成的JWT令牌返回给客户端,通常通过将令牌添加到响应的Header或Body中。
  4. 客户端携带JWT令牌:

    • 在后续的请求中,客户端需要在请求头或请求参数中携带JWT令牌,通常使用"Authorization"字段来传递令牌。
    • 例如,可以将JWT令牌添加到请求头的"Authorization"字段中,格式为"Bearer <JWT_Token>“,其中”<JWT_Token>"为生成的JWT令牌。
  5. 解析和验证JWT令牌:

    • 服务器接收到带有JWT令牌的请求后,需要对令牌进行解析和验证,以验证用户身份和授权信息。
    • 使用JwtUtils工具类中的parseJwtToken方法对JWT令牌进行解析和验证。
    • parseJwtToken方法接收一个JWT令牌作为参数,并使用之前设置的密钥SECRET_KEY对令牌进行解析。
    • 如果解析和验证成功,parseJwtToken方法将返回载荷(Payload)中的"sub"字段的值,即之前设置的用户唯一标识。
    • 如果解析和验证失败,可能是令牌过期、签名验证不通过等,服务器将拒绝请求,要求客户端重新登录获取新的令牌。
  6. 用户访问控制:

    • 在服务器端验证JWT令牌成功后,可以根据令牌中携带的用户信息(例如用户角色、权限等)进行访问控制和授权决策。
    • 服务器可以根据令牌中的信息判断用户是否有权限访问请求的资源,并执行相应的业务逻辑。

精简版案例:

客户端生成令牌:
public void generateJWT() {
    JwtBuilder builder = Jwts.builder();
    String token = builder
        // 头部
        .setHeaderParam("typ", "JWT")
        .setHeaderParam("alg", "HS256")
        // 载荷数据/过期时间
        .claim("id", 10001)
        .claim("nickName", "老王")
        // 设置过期时间,这里设置为当前时间加上一小时
        .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
        // 设置JWT的唯一标识(ID),这里使用UUID生成唯一ID
        .setId(UUID.randomUUID().toString())
        // 签名,使用HS256算法和指定的密钥(key)进行签名
        .signWith(SignatureAlgorithm.HS256, key)
        // 构造JWT令牌
        .compact();

    System.out.println(token);
}

/**
 * 服务器解析JWT
 */
@Test
public void verifyJWT() {
    // 要解析的JWT令牌
    String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MTAwMDEsIm5pY2tOYW1lIjoi6ICB546LIiwiZXhwIjoxNjkwMjc0NTg3LCJqdGkiOiIxZTY0MWExMS0yMjJkLTQ4YjMtODQ1OS05ZTlmNDUxZjIyZGQifQ.nby2Lp7nx4BLuk3SFAk0ZLPbhliLQ0l3eWOADnX5Kfc";

    // 创建JwtParser对象,用于解析JWT令牌
    JwtParser parser = Jwts.parser();

    // 解析JWT令牌并验证签名
    Jws<Claims> claimsJws = null;
    try {
        claimsJws = parser
                .setSigningKey(key) // 设置验证签名所使用的密钥(与生成JWT时使用的密钥相同)
                .parseClaimsJws(jwt); // 解析JWT令牌
        Claims body = claimsJws.getBody(); // 获取解析后的JWT令牌的载荷(Payload)
        System.out.println(body); // 输出解析后的JWT令牌的载荷内容
    } catch (Exception e) {
        // 验证失败,抛出异常
        throw new RuntimeException(e);
    }
}

常用案例

借助jjwt库来生成和解析JWT令牌。

首先,确保在项目中导入jjwt库的依赖:

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

接下来,我们定义一个简单的JWT工具类来生成和解析JWT令牌:

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

import java.util.Date;

public class JwtUtils {

    private static final String SECRET_KEY = "your-secret-key"; // 替换为自己的密钥

    public static String generateJwtToken(String subject, long expirationMillis) {
        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + expirationMillis);

        return Jwts.builder()
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public static String parseJwtToken(String jwtToken) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(jwtToken)
                .getBody();
        return claims.getSubject();
    }
}

在上面的代码中,我们定义了generateJwtToken方法用于生成JWT令牌,parseJwtToken方法用于解析JWT令牌。需要注意的是,我们在生成和解析JWT令牌时都使用了同一个密钥SECRET_KEY,确保密钥保密,不要泄露给他人。

这里的密钥可以使用算法生成

 public static String generateRandomKey() {
        // 生成256位的随机字节数组
        byte[] keyBytes = new byte[32];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(keyBytes);

        // 将字节数组转换为Base64编码的字符串
        String key = Base64.getEncoder().encodeToString(keyBytes);
        System.out.println(key + "==============");

        return key;
    }

在这段代码中,我们使用Jwts.builder()来创建JWT令牌(JSON Web Token)。Jwts是jjwt库中的一个类,用于构建JWT令牌。

接下来,我们可以使用这个JWT工具类来实现用户登录和认证的功能:

public class UserService {

    // 模拟用户数据库
    private Map<String, String> userDatabase = new HashMap<>();
    {
        userDatabase.put("user1", "password1");
        userDatabase.put("user2", "password2");
    }

    public boolean authenticateUser(String username, String password) {
        String storedPassword = userDatabase.get(username);
        return storedPassword != null && storedPassword.equals(password);
    }
}

在上面的示例中,我们假设有一个UserService类,其中authenticateUser方法用于验证用户的用户名和密码是否正确。请注意,这里只是一个简化的模拟用户数据库,实际应用中应该使用更安全和可靠的方式来存储和验证用户信息。

接下来,我们可以在主类中使用这些组件来演示JWT的使用:

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserService();

        // 用户登录,验证用户名和密码是否正确
        String username = "user1";
        String password = "password1";
        boolean isAuthenticated = userService.authenticateUser(username, password);

        if (isAuthenticated) {
            // 用户登录成功,生成JWT令牌并返回给客户端
            String jwtToken = JwtUtils.generateJwtToken(username, 3600000); // 令牌有效期1小时
            System.out.println("JWT Token: " + jwtToken);

            // 客户端在后续请求中携带JWT令牌,服务器端解析令牌并验证用户身份
            String parsedUsername = JwtUtils.parseJwtToken(jwtToken);
            System.out.println("Parsed Username: " + parsedUsername);
        } else {
            System.out.println("Authentication failed. Invalid username or password.");
        }
    }
}

在这个示例中,我们首先进行用户登录认证,如果用户名和密码验证通过,我们就生成JWT令牌并返回给客户端。在后续的请求中,客户端需要在请求头或请求参数中携带这个JWT令牌,服务器端解析令牌并验证用户身份,从而实现了用户的身份验证和授权功能。

请注意,实际应用中,我们应该更加完善和安全地管理JWT令牌,例如设置更短的过期时间、使用HTTPS等。此外,建议使用第三方库来处理JWT令牌的生成和解析,以确保安全性和正确性。

关于代码的解释

下面逐个方法来解释这段代码的含义:

  1. setSubject(subject):设置JWT令牌的主题(Subject)。在JWT中,主题是令牌所针对的用户,通常用于标识用户的唯一标识,例如用户ID或用户名。这个方法用于将用户的唯一标识作为主题设置到JWT令牌中。
  2. setIssuedAt(now):设置JWT令牌的签发时间(Issued At)。在JWT中,签发时间表示令牌的创建时间。这个方法用于将当前时间设置为令牌的签发时间。
  3. setExpiration(expirationDate):设置JWT令牌的过期时间(Expiration)。在JWT中,过期时间表示令牌的有效期截止时间。在过期时间之后,令牌将失效,需要重新登录获取新的令牌。这个方法用于将指定的过期时间设置到JWT令牌中。
  4. signWith(SignatureAlgorithm.HS256, SECRET_KEY):对JWT令牌进行签名。在JWT中,签名是为了保证令牌的完整性和安全性。签名需要一个密钥来进行加密,确保只有服务器持有密钥才能验证令牌的有效性。这个方法使用指定的签名算法(此处使用HS256)和密钥(SECRET_KEY)对令牌进行签名。
  5. compact():将JWT令牌压缩成一个字符串形式。在上面的代码中,Jwts.builder()用于构建JWT令牌的各个部分,compact()方法将JWT令牌压缩成最终的字符串形式,以便返回给客户端。

综合起来,这段代码的作用是创建一个包含指定主题、签发时间和过期时间的JWT令牌,并使用指定的签名算法和密钥对令牌进行签名,最后将JWT令牌压缩成字符串形式并返回给客户端。生成的JWT令牌将包含在响应中,客户端可以在后续的请求中携带该令牌进行身份验证和授权。服务器在接收到带有JWT令牌的请求后,可以使用相同的密钥对令牌进行解析和验证,以确认令牌的合法性和有效性。

在这段代码中,我们定义了一个静态方法parseJwtToken,用于解析JWT令牌并获取其中的主题(Subject)信息。parseJwtToken方法接收一个JWT令牌(字符串形式)作为参数,并返回解析后的主题信息。

下面逐个方法来解释这段代码的含义:

  1. Jwts.parser():创建一个JWT解析器。在jjwt库中,Jwts类的parser()方法用于创建一个JWT解析器,用于解析JWT令牌的内容。
  2. setSigningKey(SECRET_KEY):设置JWT解析器的验证密钥。在解析JWT令牌时,需要使用相同的密钥来验证令牌的签名。这个方法使用之前生成JWT令牌时使用的密钥SECRET_KEY来设置JWT解析器的验证密钥。
  3. parseClaimsJws(jwtToken):解析JWT令牌并获取Claims对象。在jjwt库中,parseClaimsJws方法用于解析JWT令牌,并返回一个Jws<Claims>对象,其中包含了JWT令牌的头部、载荷和签名等信息。
  4. getBody():从Jws<Claims>对象中获取JWT令牌的载荷(Payload)。在JWT中,载荷部分是一个JSON对象,包含了令牌的各种信息,例如主题(Subject)、签发时间(Issued At)、过期时间(Expiration)等。这个方法获取JWT令牌的载荷,并返回一个Claims对象,其中包含了令牌的所有信息。
  5. claims.getSubject():从Claims对象中获取主题信息。在JWT令牌的载荷中,通常使用"sub"字段来标识主题,即令牌所针对的用户唯一标识,例如用户ID或用户名。这个方法获取JWT令牌的主题信息,并返回给调用方。

综合起来,这段代码的作用是解析传入的JWT令牌,并从令牌的载荷中获取主题信息。这个主题信息通常用于标识令牌所针对的用户,服务器可以根据主题信息来验证用户身份和进行访问控制。如果JWT令牌的签名验证通过且令牌没有过期,parseJwtToken方法将返回令牌的主题信息,否则可能会抛出异常或返回null,取决于解析过程中是否出现异常。

总结:
JWT的使用过程包括用户登录认证、生成JWT令牌、返回令牌给客户端、客户端携带令牌访问资源、服务器解析和验证令牌、根据令牌中的信息进行用户访问控制。JWT的无状态特性使得服务器无需保存会话信息,提高了系统的性能和可伸缩性。同时,使用合适的签名算法和保密的密钥,JWT令牌能够提供一定程度的安全性,确保令牌的完整性和安全性。文章来源地址https://www.toymoban.com/news/detail-752630.html

到了这里,关于Java中JWT技术解析与实践:安全高效的身份认证的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 黑客(网络安全)技术——如何高效自学

    前几天发布了一篇 网络安全(黑客)自学 没想到收到了许多人的私信想要学习网安黑客技术!却不知道从哪里开始学起!怎么学 今天给大家分享一下,很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念,里面包含

    2024年02月06日
    浏览(45)
  • 黑客技术(网络安全)——如何高效学习

    前几天发布了一篇 网络安全(黑客)自学 没想到收到了许多人的私信想要学习网安黑客技术!却不知道从哪里开始学起!怎么学 今天给大家分享一下,很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念,里面包含

    2024年02月06日
    浏览(60)
  • 深度解析 Docker Registry:构建安全高效的私有镜像仓库

    🎈个人主页:程序员 小侯 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:大数据系列 ✨文章内容:Docker Registry 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 Docker Registry是Docker生态系统中关键的组件,负责存储

    2024年02月04日
    浏览(83)
  • HTTP深度解析:构建高效与安全网络的关键知识

    1. HTTP基础及其组件 我首先想和大家分享的是HTTP的基础知识。HTTP,即超文本传输协议,是互联网上最常用的协议之一。它定义了浏览器和服务器之间数据交换的规则,使得网页内容可以从服务器传输到我们的浏览器上。想象一下,每当你点击一个链接或输入网址时,就是HT

    2024年02月04日
    浏览(76)
  • 如何高效自学(黑客技术)方法——网络安全

    1.无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性,例如 Web 安全技术,既有 Web 渗透 2.也有 Web 防御技术(WAF)。作为一个合格的网络安全工程师,应该做到攻守兼备,毕竟知己知彼,才能百战百胜。 1.不要试图先成为一名程序员(以编程为基础的学习)再开

    2024年02月08日
    浏览(51)
  • ️️ 爬虫技术初探:如何安全高效地采集网络信息

    博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接 : 🔗 精选专栏 : 《面试题大全》 — 面试准备的宝典! 《IDEA开发秘籍》 — 提升你的IDEA技能! 《100天精通鸿蒙》 — 从Web/安卓到鸿蒙大师! 《100天精通Golang(基础入门篇)》 — 踏入

    2024年03月23日
    浏览(45)
  • 更安全、更清晰、更高效——《C++ Core Guidelines解析》

      由资深技术专家Rainer Grimm撰著的《C++ Core Guidelines解析》,从内容上说,选取了现代C++语言最核心的相关规则;从篇幅上说,对软件工程师非常友好。以“八二原则”看,这个精编解析版是一-个非常聪明的选择。同时,Rainer Grimm并没有简单照搬开源文档中的规则,而是结合自

    2024年02月08日
    浏览(45)
  • 自学(黑客技术)——网络安全高效学习方法

    前几天发布了一篇 网络安全(黑客)自学 没想到收到了许多人的私信想要学习网安黑客技术!却不知道从哪里开始学起!怎么学?如何学? 今天给大家分享一下,很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念

    2024年02月08日
    浏览(64)
  • 基础入门-ChatGPT&结合安全&融入技术&高效赋能&拓展需求

    ChatGPT是什么? ChatGPT–可能很多人被这个缩写的名字搞糊涂了,第一眼无法看出到底什么意思,GPT 的英文原文是 Generative Pre-training Transformer(预训练生成模型),业界有人将 ChatGPT 概括为聊天机器人+搜索工具+文本创造工具的组合,或者简单理解它是一个生成式 AI(内容生成器

    2024年02月07日
    浏览(61)
  • Socks5与代理IP技术探析:构建安全高效的网络通信

    1.1 握手与身份验证 Socks5协议的握手阶段通过版本协商和灵活的身份验证方式建立安全连接。这确保了通信的可靠性和用户身份的安全。 1.2 数据传输机制 Socks5通过代理实现数据传输,支持TCP和UDP协议,为用户提供了高度灵活的网络通信机制。连接一旦建立,数据可以通过代

    2024年02月04日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包