Token原理(WEB令牌)

Token在WEB系统中相当于临时令牌的作用,一般作为验证使用。JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。Token的出现主要解决了两方面问题。
Session会话机制,可以对用户信息进行存储,方便用户再次进入系统,或者进行相应的业务操作。但是,Session是存储于服务器的,会在一定的时间内消耗服务器的内存,同时,Session储存于固定的服务器中,因此,跨域问题就成了一个大麻烦。
Token将用户信息、加密算法、签名哈希进行加密发给客户端,让客户端进行存储,又有点类似于cookie机制了,但token可比cookie安全多了。

JWT的结构

JWT,即Json Web Token(以下简称jwt)即就是一种token的实现方式。一般来说,一个完整的jwt需要分为三个部分,token头、有效载荷、哈希签名 。(jwt官方网站: https://jwt.io/
在这里插入图片描述

一、JWT头
{
  "alg": "HS256",          签名使用的算法
  "typ": "JWT"             令牌类型,这里就是jwt
}

将这个对象进行BASE64URL加密就是jwt的头。

二、PAYLOAD 有效载荷
{
  "sub": "1234567890",               主题
  "name": "John Doe",                自定义字段
  "iat": 1516239022                  发布时间
}

PAYLOAD有效载荷中既可以存放一些已经定义过的字段,也可以自定义字段。

~~payload预定义的一些字段~~
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT

将这个对象同样使用BASE64URL加密并且与jwt头以点号( . )隔开。

三、VERIFY SIGNATURE 哈希签名

对jwt头和载荷信息使用指定算法进行哈希签名,确保数据的完整性。
在签名算法中需要指定一个私钥,这个私钥只存储于服务器中,不能向用户公开。
将生成的哈希签名作为第三部分与前两部分以点号隔开,就生成了一个完整的token。

JWT的存储

服务器在验证用户合法性后会生成token,并将这个token发送给客户端,由客户端(即浏览器)存储在cookie或者local storage中。
客户再次进入系统时,客户端将携带token发给服务器作验证,这时候,token一般位于HTTP请求的HEADER AUTHORITON字段中,有时,也会放在post请求的数据主体中。

JWT的优缺点

1、JWT默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。
2、当JWT未加密方法是,一些私密数据无法通过JWT传输。
3、JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
4、JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
5、JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
6、为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

JWT的实现

这里只介绍java中如何实现,其它编程语言请参考JWT官网。
1.先引入jwt所需的jar包

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

2.生成token以及验证

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

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

public class AuthTools {

    public static String sign(String userName, String userId){
        try {
            Date date = new Date(System.currentTimeMillis() + Constant.EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(Constant.TOKEN);
            //设置头部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("typ","jwt");
            header.put("alg","HS256");
            return JWT.create()
                    .withHeader(header)
                    //设置自定义载荷信息
                    .withClaim("userName",userName)
                    .withClaim("userId", userId)
                    //设置token过期时间
                    .withExpiresAt(date)     
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean verify(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(Constant.TOKEN);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (UnsupportedEncodingException e) {
            return false;
        }
    }
}



//一些用到的常量
public class Constant {

    //设置过期时间为15分钟
    public static final long EXPIRE_TIME = 15*60*1000;

    //token私钥
    public static final String TOKEN = "cabsycbiabiebciubadiugi";

}

3.验证token的生成

import ch.qos.logback.core.net.SyslogOutputStream;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.test.travel.tools.AuthTools;
import com.test.travel.tools.Constant;

import java.io.UnsupportedEncodingException;

public class TestMain {

    public static void main(String[] args) {

        String token = AuthTools.sign("username","1");
        System.out.println("用户是否合法: " + AuthTools.verify(token));

        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256(Constant.TOKEN);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);

        System.out.println("header: " + jwt.getHeader());
        System.out.println("payload:" + jwt.getPayload());
        System.out.println("signature: " + jwt.getSignature());
        System.out.println("token: " + jwt.getToken());
        System.out.println("userName: " + jwt.getClaim("userName").asString());
        System.out.println("userId: " + jwt.getClaim("userId").asString());
        System.out.println("算法: " + jwt.getAlgorithm());

    }

}


##执行结果
用户是否合法: true
header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload:eyJ1c2VyTmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTU1NTkzMDMwLCJ1c2VySWQiOiIxIn0
signature: M7b7w1Zd4jeVCGii9VJRlfTQgjD_cCtQYWyDQhCeU2s
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTU1NTkzMDMwLCJ1c2VySWQiOiIxIn0.M7b7w1Zd4jeVCGii9VJRlfTQgjD_cCtQYWyDQhCeU2s
userName: username
userId: 1
算法: HS256
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JWT(JSON Web Token)是一种基于JSON格式的安全令牌,用于在网络应用中传递声明。JWT由三个部分组成,分别是Header(头部)、Payload(负载)和Signature(签名)。 Header部分通常由两部分组成,分别是token类型和算法类型,例如: ``` { "alg": "HS256", "typ": "JWT" } ``` Payload部分是JWT的核心,包含了一些声明信息,例如用户ID、用户名、过期时间等,也可以自定义一些信息,如下所示: ``` { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } ``` Signature部分是使用私钥对Header和Payload进行签名得到的,用于验证JWT的真实性和完整性。签名的过程如下: 1. 将Header和Payload进行Base64编码,得到两个字符串 2. 将两个字符串用`.`连接起来,得到一个字符串 3. 使用私钥对字符串进行签名,得到一个密文 JWT的验证过程如下: 1. 将Header和Payload进行Base64编码,得到两个字符串 2. 将两个字符串用`.`连接起来,得到一个字符串 3. 使用公钥对密文进行验签,得到一个字符串 4. 将验签得到的字符串和第2步得到的字符串进行比较,如果相等则验证通过 JWT的优点在于它是无状态的,即服务端不需要保存任何状态信息,只需要验证JWT的合法性即可。这样可以减轻服务器的负担,提高系统的可伸缩性。同时,JWT还支持跨域访问和多语言环境,是一种非常灵活的令牌方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值