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日

相关文章

  • Java8如何将Array转换为Stream的实现代码

    要将数组转换为流,我们可以使用Java 8中新增的stream()方法。下面是Java 8中的两个示例,说明如何使用数组创建流: 1. 示例一: String[] arr = {"apple", "banana", "orange", "grape", "mango&q…

    Java 2023年5月26日
    00
  • netty中pipeline异常事件分析

    请允许我对“netty中pipeline异常事件分析”的攻略进行详细说明。 1. 理解pipeline异常事件 在Netty中,ChannelPipeline是消息处理的管道,消息在这条管道中流转,每个节点都可以做一些特定的处理。 在应用程序的运行过程中,有可能会发生一些异常情况,比如消息处理节点出错了,网络连接中断等。为了保证应用程序的健壮性,Netty提…

    Java 2023年5月25日
    00
  • Java实现简单登陆界面

    想要实现Java实现简单登录界面,需要遵循以下步骤: 步骤一:创建Java项目 在IDE中,创建一个Java项目(比如使用Eclipse),并选择创建一个Java程序。该程序将成为登录界面的入口。 步骤二:设计登录界面 使用Swing或JavaFX等Java GUI库,设计登录界面的界面元素。例如,需要一个文本框来输入用户名,一个密码框来输入密码,还需要一个…

    Java 2023年5月18日
    00
  • SpringBoot 中常用注解及各种注解作用

    来详细讲解一下SpringBoot中常用注解及各种注解作用的攻略。 1. @SpringBootApplication 这是一个复合注解,包含了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。 @Configuration:表示这是一个配置类,可以用来替代xml配置文件。 @EnableA…

    Java 2023年5月15日
    00
  • 浅谈Java中的final关键字与C#中的const, readonly关键字

    浅谈Java中的final关键字与C#中的const, readonly关键字 在Java和C#中,我们都可以使用final、const和readonly来定义常量。但是,它们在使用上有些许差异。 Java中的final关键字 在Java中,使用final关键字可以定义常量。它可以被用于修饰变量、类或方法。当用于定义变量时,final表示该变量的值一旦被赋值…

    Java 2023年5月26日
    00
  • Java使用JDBC实现Oracle用户认证的方法详解

    Java使用JDBC实现Oracle用户认证的方法 示例1:使用JDBC连接Oracle数据库 在Java中使用JDBC连接Oracle数据库,主要需要使用以下步骤: 加载数据库驱动程序; 创建数据库连接; 创建Statement对象; 执行SQL语句; 处理结果; 关闭连接。 以下是一个简单的示例代码: import java.sql.*; public …

    Java 2023年5月20日
    00
  • 使用sts工具、SpringBoot整合mybatis的详细步骤

    下面是详细步骤: 准备环境 JDK8+ Maven3.0+ SpringBoot2.0+ STS(Spring Tool Suite)/ IntelliJ IDEA 创建SpringBoot项目 使用STS或者IntelliJ IDEA创建一个新的SpringBoot项目,选择Web依赖,根据个人喜好选择模板。 在pom.xml中添加MyBatis依赖: x…

    Java 2023年5月20日
    00
  • Java实现深度搜索DFS算法详解

    Java实现深度搜索DFS算法详解 DFS简介 深度搜索(Depth First Search, DFS)是一种用于遍历或搜索树或图的算法。其基本思想是从根节点出发,尽可能深的遍历每一个节点,直到没有下一个未访问的节点,然后回溯到最近的未访问节点,并继续访问其它节点。 DFS算法流程 DFS算法的流程如下: 将起始节点添加到栈中 判断栈是否为空,如果为空则退…

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