小滴课堂—项目大课训练营笔记(1)分布式应用下的检验解决方案-JWT

什么是JWT

Json web token简称为JWT,是为了在网络的应用环境当中双方传递JSON对象的形式安全信息传递方法。这种token被设计得紧凑且是安全的,非常适用于分布式站点的单点登录场景。JWT的声明一般是用在身份提供者和服务提供者之间来验证用户的身份信息,以便从资源服务器来获取到资源,也可以增加一些其他的业务逻辑来声明信息。这种token也可以用于认证,也可以被加密使用,使用HMAC算法或者是RSA的公钥秘钥来对进行签名。

简单点来说就是,通过一定的规范来生成token,然后以解密算法逆向解密token,这样就可以获取到用户的信息了。

JWT的起源

说到JWT,我们可以来谈谈token认证和session认证有什么区别

session认证

了解http知道,http协议是一种无状态的协议,这就说明了如果用户向应用发起请求时,应用提供了用户名和密码来进行验证,那么用户再进行下次请求时,用户还需要进行用户认证才可以。因为根据http协议,应用并不可以知道是那一个用户发出的请求,所以为了让应用可以识别到是哪一位用户发出的请求,我们只可以在服务器来存储用户的登录信息,这一个登录信息会在响应的时候传递给浏览器,并保存为cookie,以便在下次请求的时候发送给应用,这样应用就可以识别来自那一个用户了,这就是传统的session认证。

session认证所存在的问题

在使用session的时候,每一个用户经过我们的应用来进行认证之后,如果认证的记录保存在内存当中的话,这就说明了下次请求还必须要请求在这一台的服务器上,这样才能获取到授权的资源。这样的话使得在分布式的应用上,限制了负载均衡器的能力,限制了应用的扩展能力。

CSRF:因为是cookie来识别的,如果被截获。用户就容易收到跨站的请求攻击

token鉴权认证

token的鉴权类似于http协议,也是无状态的,但是它不需要在服务端来保留用户的认证信息或者是会话信息。这就说明了token的认证不需要去考虑是在那一台服务器登录的,这时候就体现出来tocken的便利。

token认证流程大致如下:

1、首先用户使用用户名和密码来发送请求到服务器

2、服务器来验证了用户的信息

3、服务器通过验证后来给用户发送一个token

4、客户端存储该token,并且在每次请求的时候都会附上该token值

5、服务端进行token验证,并且返回数据

token必须要在每次发送请求的时候传递给服务端,它保存在请求头里。服务端也要有CORS的支持策略。

JWT认证的优势

(1)JWT数据量小,传输速度快

(2)JWT是以JSON的加密方式来存储在客户端当中,所以JWT是跨语言的,支持WEB上的任何形式

(3)不需要在服务端来保存信息,也就是说不依赖cookie和session,就没有了session认证的弊端

(4)单点登录具有良好的性能,token可以保存在客户端的任意位置内存当中

(5)契合移动端使用

因为具有这些优势,所以无论是单体的应用上还是分布式应用,都推荐使用JWT进行用户认证

JWT结构

JWT由标头(Header)、有效载荷(Payload)和签名(Signature),当在传输的时候,会把JWT的三个部分分别进行Base64编码后,用.进行连接形成最终的传输字符串

JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

Header

JWT的头是描述JWT元数据的JSON对象,alg表示了签名算法,默认是HS256,typ表示令牌的类型,JWT令牌统一是写JWT,最后使用Base64算法将转成JSON对象转换成字符串

{
"alg":"HS256"
"typ":"JWT"
}

Payload

它是存放JWT有效信息的地方,有效信息包含了有标准中的注册声明、公共的声明、私有的声明

标准中的注册声明:

(1)iss:jwt发行人

(2)sub:面向的用户

(3)aud:用户

(4)exp:到期的时间

(5)iat:发布的时间

(6)jti:唯一表示JWT

公共声明:在公共声明中可以添加信息,一般添加与用户相关的信息或者是业务的必要信息,不推荐添加敏感信息,因为可以被解密

私有声明:是共同定义的声明,不推荐存放敏感信息

Signature

这个部分是对上面的两个进行数据签名,使用base64编码后的header、payload数据,通过指定的算法生成哈希,确保数据不会被篡改。它的原理是这样的,首先生成一个密钥,这个密钥存储在服务器当中,并且不会向用户公开,然后使用指定的签名算法,最后面就构成了JWT对象

HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

在Java中使用JWT

官网:JSON Web Token Libraries - jwt.io

可以看到在官网当中有JWT的六种使用方法,这里就使用最多人使用也是最推荐使用的Java-jwt

使用方法

在pom.xml当中添加依赖

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

编写测试代码

    @Test
    public void testToken(){
        //token过期时间为20s
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND,20);

        String token = JWT.create()
                .withHeader(new HashMap<>())   //header
                .withClaim("xdclassId",10)   //Payload
                .withClaim("xdclassName","小明")
                .withExpiresAt(calendar.getTime())           //过期的时间
                .sign(Algorithm.HMAC256("I34ADAS"));
        System.out.println(token);
    }

生成token

注意:多次运行方法的token字符串内容是不一致的,不管payload信息有没有变化。原因是JWT携带了超时时间,所以每次生成的token都会不一样

解析JWT字符串

    @Test
    public void testGetToken(){
        //解析对象,要与创建的算法保持一致
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("!34ADAS")).build();
        //指定解析的token
        DecodedJWT decodedJWT = jwtVerifier.verify("这里输入打印出来的token");
   //获取解析后的信息
        Claim xdclassId = decodedJWT.getClaim("xdclassId");
        Claim xdclassName = decodedJWT.getClaim("xdclassName");
        System.out.println(xdclassId.asInt());
        System.out.println(xdclassName.asString());
        System.out.println(decodedJWT.getExpiresAt());
    }

报错异常可以把token的过期时间设置的久一点~

更多学习笔记课程资料都在wx:xdclass99。添加客服领取

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值