hutool-JWT

package com.litongjava.tio.boot.hello.AController;

import cn.hutool.jwt.JWTUtil;
import com.litongjava.tio.http.common.HeaderName;
import com.litongjava.tio.http.common.HeaderValue;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;
import com.litongjava.tio.utils.resp.RespVo;

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

/**
 * token永不过期
 */
@AController
@RequestPath("/auth")
public class AuthController {

  // 使用HmacSHA256签名算法的密钥
  byte[] key = "litongjava".getBytes();
  // 用于存储tokens的Map
  private static Map<String, String> tokenStore = new HashMap<>();

  @RequestPath("/login")
  public HttpResponse login(HttpRequest request, String username, String password) {
    if (isValidUser(username, password)) {
      // 生成JWT token
      String accessToken = createJWTToken(username, key);

      // 将token存储到Map中
      tokenStore.put(username, accessToken);

      // 创建HttpResponse,并添加token作为头部
      HeaderName headerName = HeaderName.from("Authorization");
      HeaderValue headerValue = HeaderValue.from("Bearer " + accessToken);

      HttpResponse httpResponse = Resps.json(request, RespVo.ok());
      httpResponse.addHeader(headerName, headerValue);
      return httpResponse;
    } else {
      return Resps.json(request, RespVo.fail("Invalid username or password"));
    }
  }

  @RequestPath("/verifyToken")
  public RespVo verifyToken(String token) {
    // 验证token是否有效
    if (isValidToken(token)) {
      return RespVo.ok();
    } else {
      return RespVo.fail("Token is invalid or expired");
    }
  }

  private boolean isValidUser(String username, String password) {
    // 在这里实现您的用户验证逻辑
    // 暂时返回true模拟验证成功
    return true;
  }

  public static String createJWTToken(String username, byte[] key) {
    // 载荷,可根据需要添加更多数据
    Map<String, Object> payload = new HashMap<>();
    payload.put("username", username);

    // 设置过期时间,例如1小时后
    long expirationMillis = System.currentTimeMillis() + 3600000; // 1小时 = 3600000毫秒
    Date expiration = new Date(expirationMillis);
    payload.put("exp", expiration.getTime() / 1000); // JWT通常使用秒为单位的时间戳

    // 生成JWT token
    return JWTUtil.createToken(payload, key);
  }

  private boolean isValidToken(String token) {
    // 使用相同的密钥验证token
    return JWTUtil.verify(token, key);
  }
}

代码展示了一个用于身份验证和令牌管理的 AuthController 类,它是使用 tio-boot 框架编写的。这个类提供了用户登录和验证令牌的功能。下面是对代码的关键点的解释:

  1. 类定义和成员变量:

    • 类被注解为 @RequestPath("/auth"),这意味着它处理以 /auth 开头的 HTTP 请求路径。
    • key 是用于 JWT 签名的密钥,这里是一个硬编码的字符串 "litongjava"。在实际应用中,这个密钥应该是安全生成和存储的。
    • tokenStore 是一个用于存储生成的令牌的静态映射(Map)。
  2. login 方法:

    • 当用户尝试登录时,此方法被调用。
    • 它首先调用 isValidUser 方法来验证用户名和密码。
    • 如果验证成功,它调用 createJWTToken 方法生成 JWT 令牌。
    • 然后,生成的令牌被存储在 tokenStore 中,并以 Authorization 头的形式添加到响应中。
    • 最后,方法返回一个 HttpResponse 对象,该对象包含 JSON 格式的响应。
  3. verifyToken 方法:

    • 此方法用于验证传入的令牌是否有效。
    • 它调用 isValidToken 方法来检查令牌。
    • 根据令牌的有效性,它返回一个包含相应消息的 RespVo 对象。
  4. createJWTToken 方法:

    • 这是一个静态辅助方法,用于生成带有用户信息和过期时间的 JWT 令牌。
    • 它将用户名作为载荷的一部分,并计算一个小时后的时间作为令牌的过期时间。
    • 这个方法使用 JWTUtil.createToken 方法生成令牌。
  5. isValidToken 方法:

    • 用于验证给定令牌的有效性。
    • 它使用相同的密钥 key 来验证令牌。
  6. 安全性和实用性的考虑:

    • 密钥应该安全生成和存储,不应硬编码在代码中。
    • 在生产环境中,令牌应该有一个合理的过期时间,并且应该提供令牌刷新的机制。
    • 用户验证逻辑(isValidUser 方法)应该实现实际的验证过程,例如检查数据库中的用户凭据。
    • 令牌存储(tokenStore)应考虑使用更安全和可扩展的存储解决方案,如数据库或缓存系统。在内存中存储令牌可能不适合大规模或生产环境。