Java JWT生成token信息

什么时候使用 JWT

JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。JWT 虽然对于大多数网站都没有用,但是有几种情况它是很有用的。如果你正在构建从服务器到服务器或客户端到服务器(如:移动应用 APP 或单页面应用)的 API服务,那么使用 JWT 是非常明智的。

JWT使用流程

  1. 初次登录:用户初次登录,输入用户名密码
  2. 密码验证:服务器从数据库取出用户名和密码进行验证
  3. 生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT
  4. 返还JWT:服务器的HTTP RESPONSE中将JWT返还
  5. 带JWT的请求:以后客户端发起请求,HTTP REQUEST
  6. HEADER中的Authorizatio字段都要有值,为JWT
  7. 服务器验证JWT

2. JWT的原则

JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,如下所示。

{
"UserName": "Chongchong",
"Role": "Admin",
"Expire": "2018-08-08 20:15:56"
}
之后,当用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名(有关详细信息,请参阅下文)。服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展。

3. JWT的数据结构

典型的,一个JWT看起来如下图。

该对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。注意JWT对象为一个长字串,各字串之间也没有换行符,此处为了演示需要,我们特意分行并用不同颜色表示了。每一个子串表示了一个功能块,总共有以下三个部分:

JWT的三个部分如下。JWT头、有效载荷和签名,将它们写成一行如下。我们将在下面介绍这三个部分。

3.1 JWT头

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

{
"alg": "HS256",
"typ": "JWT"
}
在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。

最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

3.2 有效载荷

有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。

iss:发行人

exp:到期时间

sub:主题

aud:用户

nbf:在此之前不可用

iat:发布时间

jti:JWT ID用于标识该JWT

除以上默认字段外,我们还可以自定义私有字段,如下例:

{
"sub": "1234567890",
"name": "chongchong",
"admin": true
}

请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。JSON对象也使用Base64 URL算法转换为字符串保存。

案例演示

下面显示了一个登录请求成功之后服务端返回的Token,它由编码头部(header)、编码有效载(payload)和签名(signature)通过(.)拼接而成:
 

JWT并不对数据进行加密,而是对数据进行签名,保证不被篡改。除了在登录中可以用到,在进行邮箱校验和图形验证码也可以用到。

JWT缺点及对应的解决方案

登录状态信息续签问题。比如设置token的有效期为一个小时,那么一个小时后,如果用户仍然在这个web应用上,这个时候当然不能指望用户再登录一次。判断还有多久这个token会过期,在token快要过期时,返回一个新的token。

用户主动注销。JWT并不支持用户主动退出登录,当然,可以在客户端删除这个token,但在别处使用的token仍然可以正常访问。为了支持注销,我的解决方案是在注销时将该token加入黑名单。可以给用户加一个登录状态字段。登录之后这个字段为1。然后退出之后这个字段为0。如果退出了,就算有JWT还是退出状态了。

Java maven依赖

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

JWT加解密

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author hudy
 * @date 2024/6/7
 */
public class JWTEncrypt {

  /**
   * 分配给供应商的签发主体
   */
  private static final String JWT_ISSUER = "明文内容加密";
  // 签名密钥
  private static final String APP_SECRET = "33db7be3237f0a29f2150aaca789fa6f";

  // Bearer令牌
  private static final String BEARER = "Bearer ";

  // 日志记录器
  private static final Logger logger = LoggerFactory.getLogger(JWTEncrypt.class);

  // 生成一个长期有效的Token
  public static String genToken() throws JWTCreationException, UnsupportedEncodingException {
    return BEARER + JWT.create()
        .withIssuer(JWT_ISSUER)
        .withIssuedAt(new Date())
        .sign(Algorithm.HMAC256(APP_SECRET));
  }

  // 验证有效信用组织
  public static boolean verifyValidCreditOrg(String jwtSignToken, String appToken) {
    try {
      JWTVerifier verifier = JWT.require(Algorithm.HMAC256(appToken)).build();
      verifier.verify(jwtSignToken);
      return true;
    } catch (Exception e) {
      logger.error("JWT token验证异常,原因:{}", e);
    }
    return false;
  }

  // 获取签发者
  public static String getIssuer(String jwtSignToken) throws RuntimeException {
    try {
      return JWT.decode(jwtSignToken).getIssuer();
    } catch (Exception e) {
      logger.error("获取JWT的appkey发生异常,原因:{}", e);
      throw new RuntimeException("非法请求客户端");
    }
  }

  // 获取签发时间戳
  public static Long getIssuedAt(String jwtSignToken) throws RuntimeException {
    try {
      return JWT.decode(jwtSignToken).getIssuedAt().getTime() / 1000;
    } catch (Exception e) {
      logger.error("获取JWT的appkey发生异常,原因:", e);
      throw new RuntimeException("非法请求客户端");
    }
  }

  public static void main(String[] args) throws UnsupportedEncodingException {
    // 生成token
    String authorization = JWTEncrypt.genToken();
    System.out.println("请求头授权信息,header token=" + authorization);

    // 验证token
    String jwtSignToken = authorization.substring(BEARER.length());
    boolean verified = JWTEncrypt.verifyValidCreditOrg(jwtSignToken, APP_SECRET);
    System.out.println("验证结果=" + verified);

    // 解析签发主体
    String issuer = JWTEncrypt.getIssuer(jwtSignToken);
    System.out.println("签发主体=" + issuer);
  }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中,可以使用com.auth0库来实现JWT生成和验证。首先,你需要在你的项目中添加该库的依赖: ```xml <!--JWT--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency> ``` 接下来,你可以使用以下代码创建一个JWTtoken: ```java String token = JWTUtils.createToken(1L); ``` 请注意,在上面的例子中,我将token的过期时间设置为10秒。 接下来,如果你想验证token并获取其中的信息,你可以使用以下代码: ```java try { Map<String, Claim> stringClaimMap = JWTUtils.verifyToken(token); Long id = stringClaimMap.get("id").asLong(); System.err.println("用户id是:" + id); } catch (Exception e) { e.printStackTrace(); } ``` 上面的代码会尝试验证token,并从中获取id这个字段的值。如果token已经过期,会抛出TokenExpiredException异常。 为了处理token过期的情况,你可以使用以下代码: ```java try { // 上面的token被我设置成了10秒过期 Thread.sleep(11000L); JWTUtils.verifyToken(token); // 这里定向捕获登录过期异常 } catch (TokenExpiredException e) { // 写过期逻辑 System.err.println("登录过期"); } catch (Exception e) { e.printStackTrace(); } ``` 上面的代码会捕获TokenExpiredException异常,你可以在此处编写处理过期逻辑。 最后,你可以使用以下代码来验证token和获取其中的信息: ```java public static Map<String, Claim> verifyToken(String token) throws Exception { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build(); DecodedJWT jwt = verifier.verify(token); return jwt.getClaims(); } ``` 上面的代码会使用之前设置的密钥来验证token,并返回包含token中所有声明的Map。 这样,你就可以在Java中使用JWT生成token了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JWT介绍及用JAVA使用JWT生成token](https://blog.csdn.net/weixin_43085439/article/details/105838751)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值