Java中使用JWT生成Token进行接口鉴权实现方法

为了在Java中使用JWT生成Token进行接口鉴权,我们需要以下步骤:

1. 引入依赖

我们需要在项目中引入一个JWT依赖,例如Java JWT(https://github.com/auth0/java-jwt)。

Maven坐标如下:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.2</version>
</dependency>

2. 生成Token

我们可以使用如下代码在Java中生成一个JWT Token:

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

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

public class JWTUtils {

    /**
     * 生成JWT Token
     * @param issuer    签发人
     * @param subject   主题
     * @param expireSeconds     过期时间,单位为秒
     * @param secret    密钥
     * @return  JWT Token
     */
    public static String generateToken(String issuer, String subject, long expireSeconds, String secret) {
        // 设置过期时间
        Date expireDate = new Date(System.currentTimeMillis() + expireSeconds * 1000);
        // 设置Header
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");
        // 生成Token
        String token = JWT.create().
            withHeader(header).
            withIssuer(issuer).
            withSubject(subject).
            withExpiresAt(expireDate).
            sign(Algorithm.HMAC256(secret));
        return token;
    }

}

其中,参数分别表示:

  • issuer:签发人
  • subject:主题
  • expireSeconds:过期时间,单位为秒
  • secret:密钥

使用JWT生成Token的算法一般采用HMAC加密算法,常见的有HMAC256和HMAC512。

为方便演示,我们在主函数中调用该方法并输出生成的Token:

public class Main {

    public static void main(String[] args) {
        String issuer = "test";
        String subject = "test-token";
        long expireSeconds = 3600;
        String secret = "my-secret";    // 这里应该放在配置文件中,不应该明文写在代码中

        String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
        System.out.println(token);
    }

}

输出的Token如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0Iiwic3ViIjoidGVzdC10b2tlbiIsImV4cCI6MTQ4MzAwNjc5MX0.9qCZ9UBpE5Jk8VTDeYACScJf_kwSp-CWr5zgG-Dgys4

3. 验证Token

我们可以使用如下代码在Java中验证一个JWT Token:

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

public class JWTUtils {

    /**
     * 验证JWT Token
     * @param token JWT Token
     * @param secret    密钥
     * @return  是否验证通过
     */
    public static boolean verifyToken(String token, String secret) {
        try {
            // 创建验证器并设置Issuer和密钥
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
                .withIssuer("test")
                .build();
            // 验证Token
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}

验证Token的时候需要进行以下几项检验:

  • 是否有效(例如过期或者被篡改)
  • 是否由合法的签发人签发
  • 是否由合法的密钥签名

同样,我们在主函数中调用该方法并输出验证结果:

public class Main {

    public static void main(String[] args) {
        String issuer = "test";
        String subject = "test-token";
        long expireSeconds = 3600;
        String secret = "my-secret";    // 这里应该放在配置文件中,不应该明文写在代码中

        String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
        boolean result = JWTUtils.verifyToken(token, secret);
        System.out.println(result);
    }

}

输出的结果为:

true

示例1

我们可以将上述两个步骤结合起来并应用于一个简单的接口鉴权上,示例代码如下:

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

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

    private String secret = "my-secret";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 获取Authorization Header
        String authorization = request.getHeader("Authorization");
        if (authorization == null || authorization.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        // 校验Token
        try {
            // 创建验证器并设置Issuer和密钥
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
                .withIssuer("test")
                .build();
            // 验证Token
            DecodedJWT jwt = verifier.verify(authorization);
            return true;
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
    }

}

该示例定义了一个拦截器,在请求进入Controller之前验证JWT Token的有效性。如果Token验证通过则放行,否则返回401 Unauthorized错误。

示例2

我们可以将JWT生成Token的代码应用于一个实际的业务场景中,例如在用户登录成功后生成一个Token并返回给客户端,客户端在后续请求中携带该Token以进行接口鉴权。

该示例利用Spring Boot框架搭建,代码如下:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestBody UserCredentials credentials) {
        // 根据用户名和密码从数据库中查询用户信息
        User user = userService.getUserByCredentials(credentials.getUsername(), credentials.getPassword());
        if (user == null) {
            return ResponseEntity.badRequest().body("用户名或密码错误");
        }

        // 生成Token并返回给客户端
        String issuer = "test";
        String subject = String.format("user-%d", user.getId());
        long expireSeconds = 3600;
        String secret = "my-secret";

        String token = JWTUtils.generateToken(issuer, subject, expireSeconds, secret);
        return ResponseEntity.ok(token);
    }

    @GetMapping("/profile")
    public ResponseEntity<User> getProfile(HttpServletRequest request) {
        // 从Token中解析出用户ID
        int userId = getUserIdFromToken(request);
        if (userId <= 0) {
            return ResponseEntity.badRequest().build();
        }

        // 根据用户ID从数据库中查询用户信息
        User user = userService.getUserById(userId);
        if (user == null) {
            return ResponseEntity.notFound().build();
        }

        // 返回用户信息
        return ResponseEntity.ok(user);
    }

    private int getUserIdFromToken(HttpServletRequest request) {
        // 从Authorization Header中解析出Token
        String authorization = request.getHeader("Authorization");
        if (authorization == null || authorization.isEmpty()) {
            return -1;
        }
        String token = authorization.substring("Bearer ".length());

        // 解析Token,获取UserId
        try {
            DecodedJWT jwt = JWT.decode(token);
            String subject = jwt.getSubject();
            int userId = Integer.parseInt(subject.split("-")[1]);
            return userId;
        } catch (Exception e) {
            return -1;
        }
    }

}

该示例中,客户端需要先调用“/user/login”接口进行登录,登录成功后服务器会返回一个JWT Token;客户端在后续的请求中需要在Authorization Header中携带该Token,例如:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0Iiwic3ViIjoidXNlci0xIiwiZXhwIjoxNDgzMDAyNjUwfQ.Ykn7x8K0Vwlf2kfjFMnLqmaA0O4SpnJHp3aY5oDtKZs

服务器在接收到请求后会校验Token的有效性,并从Token中解析出用户ID,再使用该用户ID从数据库中查询用户信息并返回给客户端。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中使用JWT生成Token进行接口鉴权实现方法 - Python技术站

(1)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • java中几种常见的排序算法总结

    对于“java中几种常见的排序算法总结”的攻略,我们可以通过以下步骤来进行详细讲解: 一、排序算法简介 在介绍具体的排序算法之前,我们需要了解一些基础概念。排序算法是指对一个数据集合进行排序的过程,其中涉及到的一些重要概念包括: 稳定性:如果存在相同的元素,排序前和排序后这些元素的相对位置是否发生了改变。稳定的排序算法会保留相同元素之间的顺序关系,不稳定的排…

    Java 2023年5月19日
    00
  • SpringMVC实现文件上传下载的全过程

    OK,SpringMVC实现文件上传下载的全过程可以包含以下几个步骤: 添加MultipartResolver配置 在SpringMVC配置文件中,添加MultipartResolver配置,用于处理文件上传的请求。示例代码如下: <bean id="multipartResolver" class="org.spring…

    Java 2023年6月15日
    00
  • JavaMail实现发送超文本(html)格式邮件的方法

    JavaMail是一个用于处理电子邮件的Java API,可发送和接收邮件。要发送HTML格式的邮件,可以按照以下步骤进行: 步骤1: 导入包 import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.P…

    Java 2023年6月15日
    00
  • SpringBoot基于数据库实现定时任务过程解析

    下面是关于“Spring Boot基于数据库实现定时任务过程解析”的完整攻略。 1. 背景 定时任务在业务逻辑中经常被使用,而且很多时候任务调度需要依赖于数据库中的数据。Spring Boot中提供了很方便的方式来实现定时任务的功能,而且也支持基于数据库的方式来实现任务调度,本文将详细讲解如何使用Spring Boot实现基于数据库的定时任务调度。 2. 实…

    Java 2023年5月26日
    00
  • Android发送GET与POST请求的DEMO详解

    下面我将为你详细讲解“Android发送GET与POST请求的DEMO详解”这个主题,包括以下几个方面的内容: 什么是HTTP请求 Android中发送HTTP请求的方式 完整示例:Android发送GET请求 完整示例:Android发送POST请求 什么是HTTP请求 HTTP(HyperText Transfer Protocol)是一种用于传输数据的…

    Java 2023年6月15日
    00
  • java中使用interrupt通知线程停止详析

    Java中使用interrupt通知线程停止详析 概述 在Java多线程编程中,有时候需要在某个条件满足时中断线程的执行。Java中提供了一种机制,即通过中断(interrupt)的方式通知线程停止。本文将详细阐述Java中使用interrupt通知线程停止的完整攻略。 了解中断机制 在Java中,线程有一个boolean类型的中断标记,初始值为false。…

    Java 2023年5月25日
    00
  • Spring boot 整合 Redisson实现分布式锁并验证功能

    下面我将为您详细讲解”Spring boot整合Redisson实现分布式锁并验证功能”的完整攻略。 简介 Redis是一个开源的,使用C语言开发的,支持网络,可基于内存或者磁盘的数据结构服务。Redisson是面向Java的Redis客户端,提供了丰富的接口和功能,其中包括了Redis的分布式锁实现。 Spring Boot是基于Spring框架的快速开发…

    Java 2023年6月3日
    00
  • Java的Struts框架报错“ChainNotFoundException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“ChainNotFoundException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中没有正确配置ActionChain,则可能会出现此。在这种情况下,需要检查配置文件以解决此问题。 类路径问题:如果类路径不正确,则可能会出现此。在种情况下,需要检查类路径以解决此问题。 以下是两个实例: …

    Java 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部