JWT学习并测试简单的token解密与加密

JWT的全称为Json Web Token,它可以帮助消息在Web层安全传递。
抛弃以前的cookie和session,jwt最重要的一个特点是无状态
以前是cookie存在客户端本地,sessionid存储在服务器,同时寄生于cookie。
前者存在不安全性,可能存在cookie欺骗工具,后者若是小数据还好说,若是大数据,则加大了服务器的压力。
至此,token它诞生了。它比较与cookie有如下一些优点

  • 支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的;
  • 无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session;
  • 无需绑定到一个特殊的身份验证方案(传统的用户名密码登陆),只需要生成的token是符合我们预期设定的即可;
  • 避免CSRF跨站伪造攻击,是因为它不依赖于cookie;

首先我们来谈谈JWT的组成吧
它是由header(消息头)payload(载荷)signature(签名) 三部分组成

1、header头部主要是包含以下一些信息:

  • 主要采用的key-value来阐述信息
  • typ:代表是消息体类型,这里指的是JWT
  • alg:采用的加密算法,默认是HS256(HMAC-SHA256),当然你可以指定其他类型的算法

2、payload主体主要是包含以下一些信息:

  • payload是存在需要发送的数据,可以支持自定义数据,当然也是有如下默认数据可以填入
  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

你也可以自定义为

{
	“name”:xxx	,
	“age”:xxx
}

3、signature代表是签名:

  • 签名是根据你设置的秘钥和加密算法来进行加密的

好的,理论说完了,我们开始来一个实战吧

请在你的maven下加入下面配置信息

		<!--单元测试-->
        <groupId>junit</groupId>
    	<artifactId>junit</artifactId>
    	<version>4.12</version>

        <!--lombok 注解式开发-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>

		<!--JWT 包-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.1</version>
        </dependency>

上面我用到了lombok注解开发,如果你没有接触过lombok,你需要去插件商店下载lombok,如下
在这里插入图片描述
我的包结构如下(实际只用到下面贴出代码的三个class)
在这里插入图片描述

/*TokenUtils.java*/
package com.ysj.pojo;
import com.auth0.jwt.*;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

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

@SuppressWarnings("all")
public class TokenUtils {
    // 设置过期时间为30分钟
    private static final long EXPIRATION_TIME = 30*60*1000;

    // 设置加密字符串,要足够复杂足够乱
    private static final String SECRET_KEY = "<sda122D4dD4AS5SF894FS5>?sd!@21fDADsdadgrhdfop";

    // 根据token来 生成一个加密的token字符串
    public String getToken(Token token){
        // 设置过期时间
        Date lastDate = new Date(System.currentTimeMillis() + EXPIRATION_TIME);
        // 选择算法
        Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
        // 设置header
        Map<String,Object> header = new HashMap<>();
        header.put("typ","JWT");
        header.put("alg","HS256");

        // 生成token
        return JWT.create()
                .withHeader(header)
                .withClaim("userid",token.getUserid())
                .withClaim("name",token.getName())
                .withClaim("age",token.getAge())
                .withClaim("lastTime",token.getLastTime())
                .withExpiresAt(lastDate)
                .sign(algorithm);
    }

    // 获取token数据
    public Token getTokenData(String tokenString){

        // 对token的加密字符串进行解密
        DecodedJWT jwt = JWT.decode(tokenString);

        // 通过Token类的建造者模式来实例化类,注意builder是一个静态方法
        Token token = Token.builder()
             .userid(jwt.getClaim("userid").asString())
             .name(jwt.getClaim("name").asString())
             .age(jwt.getClaim("age").asInt())
             .lastTime(jwt.getClaim("lastTime").asDate()).build();
        return token;
    }

    // 创建一个token
    public String createToken(String userid,String name,int age){

        // 创建初始时间日期
        Date date = new Date();

        Token token = Token.builder()
                .userid(userid)
                .name(name)
                .age(age)
                .lastTime(date)
                .build();
        return this.getToken(token);

    }

}

/*Token.java*/
package com.ysj.pojo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder()
public class Token {
    private String userid;
    private String name;
    private int age;
    private Date lastTime;
}

下面是测试类

package com.ysj.testPackage;

import com.ysj.pojo.Token;
import com.ysj.pojo.TokenUtils;
import org.junit.jupiter.api.Test;


public class testToken {

    @Test
    public void testTokenOperation(){
        TokenUtils tokenUtils = new TokenUtils();

        String tokenString = tokenUtils.createToken("ysj66666","凌寒天",20);
        System.out.println("------生成token-----------\n"+tokenString);
        Token tokenData = tokenUtils.getTokenData(tokenString);
        System.out.println("------获取token数据-----------\n"+tokenData.toString());
    }
}

输出如下
在这里插入图片描述
加密字符串是以. 进行分割的,总共有三部分 (header,payload,signature) ,所以有三个点,每个点对应一个加密字符串。
服务端用秘钥进行对加密字符串的解密,获取用户信息并返回。
这就是简单的token加密与解密测试。
在这里插入图片描述

在 C# 中,要解密 JSON Web Token (JWT) 使用非对称加密,通常会涉及到公钥和私钥的操作。JWT 使用的是 JWK (JSON Web Key) 格式来表示密钥,其中包括公钥(可以公开)和私钥(应保密)。当你收到一个 JWT,并且知道其对应的私钥(作为字符串形式),你可以使用 `System.IdentityModel.Tokens.Jwt` 类库来解密。 以下是基本步骤: 1. **获取私钥字符串**: 将私钥字符串转换成 `RSAParameters` 对象,这是 .NET Core 库需要的格式。这可以通过一些库(如 `JsonWebKeyConverter`)来完成,或者手动解析字符串。 ```csharp string privateKeyString = ... // 你的私钥字符串 var rsaParams = JsonConvert.DeserializeObject<RSAParameters>(privateKeyString); var rsaSecurityKey = new RsaSecurityKey(rsaParams); ``` 2. **创建 JwtSecurityTokenHandler**: 这是用来处理 JWT 的验证和解密工具。 ```csharp var handler = new JwtSecurityTokenHandler(); ``` 3. **解密 JWT**: 使用 `ValidateToken` 方法尝试解密 JWT。它接受 JWT、有效的安全令牌验证回调(这里使用私钥解密)以及其他验证选项。 ```csharp try { var jwtToken = handler.ReadJwtToken(tokenString, ValidateSignatureAsync, rsaSecurityKey); string decodedPayload = Encoding.UTF8.GetString(jwtToken.Payload.Data); // 解码后的payload内容 } catch (Exception ex) { // 处理解密失败的情况 } async Task ValidateSignatureAsync(JwtSecurityToken token, SecurityToken validationContext) { // 检查签名,如果使用的是RS256,此方法应检查是否成功匹配私钥签名 return token.SignatureAlgorithm == SecurityAlgorithms.RS256 && token.Signature.Verify(validationContext); } ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨小街

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值