JWT的知识总结

一,JWT简介

        JWT全称叫json web token,通过数字签名的方式,以json对象为载体,在不同的服务终端之间安全的传输信息。

        JWT在前后端分离系统,或跨平台系统中,通过JSON形式作为WEB应用中的令牌(token),用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中,还可以完成数据加密、签名等相关处理。

        前端应用在访问后端应用时,会携带令牌(token),后端应用在接到令牌(token)后,会验证令牌(token)的合法性。从而决定前端应用是否能继续访问。JWT还可以系统之间进行信息传递,A系统通过令牌对B系统进行数据传输,在传输过程中,可以完成数据的加密,B系统拿到数据后,通过签名进行验证,从而判断信息是否有篡改。

二,JWT的应用

        JWT最常见的场景就是授权认证,一旦用户登录,后续每个请求都将包含JWT,系统在每次处理用户请求之前,都要先进行JWT安全校验,通过之后再进行处理。

1、授权

        这是JWT最常见方案,一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。

2、信息交换

        JWT是在各方之间安全地传输信息的好方法,可以验证传输内容是否遭到篡改。

三,JWT和session的比较

session存在的问题:

        1、每个用户经过我们的应用认证之后,将认证信息保存在session中,由于session服务器中对象,随着认证用户的增多,服务器内存开销会明显增大。

        2、用户认证之后,服务端使用session保存认证信息,那么要取到认证信息,只能访问同一台服务器,才能拿到授权的资源。这样在分布式应用上,就需要实现session共享机制,不方便集群应用。

        3、因为session是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

        JWT认证基于令牌,该令牌存储在客户端。但认证由服务器端进行,解决服务器内存占用问题。当用户提交用户名和密码时,在服务器端认证通过后,会生成token令牌。然后将令牌响应给客户端浏览器。客户端浏览器会在本地存储令牌。在客户端再次请求服务器接口时,每次都会携带JWT,在服务器验证通过后,再继续访问服务器资源

JWT的优势

        1、简洁,可以通过URL、POST参数或Http  header发送,因为数据量小,传输速度快。

        2、自包含,负载(属于JWT的一部分)中包含了用户所需要的信息,不需要在服务器端保存会话信息,不占服务器内存,也避免了多次查询数据库,特别适用于分布式微服务。

        3、因为token是以json加密的形式保存在客户端的,所以JWT可以跨语言使用,原则上任何WEB形式都支持。

四,JWT认证流程

        1、前端将用户名和密码发送到后端服务器。后端服务器对用户名和密码验证通过后,将用户信息作为JWT Payload负载,将其与头部进行Base64编号拼接后签名,形成JWT。形成的JWT本质上就是一个形如lll.zzz.xxx的字符串。

        2、后端将JWT字符串作为登陆成功的返回结果返回给客户端。前端可以将返回结果保存在localStorage,退出登陆时,前端删除保存的JWT即可。

        3、前端在每次请求时将JWT放入HTTP  Header中的Authorization位。

        4、后端检查是否存在,如果验证JWT有效,后端就可以使用JWT中包含的用户信息。

五,JWT组成

        JWT其实就是一段字符串,由标头有效负载签名这三部分组成,用  .  拼接

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2Mjc5NzA5NDUsInVzZXIiOiJ7XCJpZFwiOjMsXCJuYW1lXCI6XCLlkInlkIlcIixcInB3ZFwiOlwiMzMzXCJ9In0.NvGdUjFLJWj_ZzhY9Qp--NkZgK1QGQtQjiCB7lEsFTg

        Header{  //标头    

                ‘typ’:’JWT’,   表示token类型    

                ‘alg’:’HS256’   表示签名算法

        }

它会使用 Base64编码组成JWT结构的第一部分。

        Payload //有效负载 {

                   ‘userCode’:’43435’,

                  ‘name’:’john’,  

                ‘phone’:'13950497865'

                }

        用于存储主要信息,使用 Base64编码组成JWT结构的第二部分。由于该信息是可以被解析的,所以,在信息中不要存放敏感信息。

Signature签名

        前面两部分都使用Base64进行编码,前端可以解开知道里面的信息, Signature需要使用编码后的header和payload以及我们提供的一密钥,然后使用header中指定的签名算法进行签名,以保证JWT没有被篡改过。

        使用Signature签名可以防止内容被篡改。如果有人对头部及负载内容解码后进行修改,再进行编码,最后加上之前签名组成新的JWT。那么服务器会判断出新的头部和负载形成的签名和JWT附带的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

六,JWT的环境搭建

在pom.xml文件中导入依赖:

 <dependency>    

        <groupId>com.auth0</groupId>    

        <artifactId>java-jwt</artifactId>    

        <version>3.13.0</version>

 </dependency>

七,JWT的创建

private static String signature = "lovo!";
    public String createToken(Map<String,String> map){
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MINUTE,30);
 	//header标头可不写,默认为JWT
        JWTCreator.Builder builder = JWT.create();
        for(String key : map.keySet()){
 	    //payload负载,具体数据
            builder.withClaim(key,map.get(key));
        }
        String token = builder.withExpiresAt(c.getTime())
                .sign(Algorithm.HMAC256(signature));
        return token;
    }

八,JWT的解码

public String verify(String token,String key){
        //创建解码对象
        JWTVerifier jwtVerifier =  JWT.require(
                Algorithm.HMAC256(signature)).build();
        DecodedJWT dj =  jwtVerifier.verify(token);
        String value = dj.getClaim(key).asString();

        return value;
    }

        在解码过程中,如果解码失败,则抛出异常。

九,JWT的发送和接收

在应用控制器Controller中,通过响应头发送给客户端。

response.setHeader("token", JWT字符串);

客户端通过axios接收响应头,并保存在sessionStorage中。

var param = {name:"tom",pwd:"111"};
await axios.get("/user/login",{params:param}).then(e => {
         var info = e.data;//响应消息体
         sessionStorage.setItem("token",e.headers.token);
});

客户端再次请求,读取localStorage的JWT信息,以请求头的方式,发送给服务器

var tk = localStorage.getItem("token");

axios.get("/user/getLoginUser",
   {headers:{token:tk}}).then(e => {
                                 info = e.data;
                            });

服务器从请求头中得到jwt字符串,解析后,得到数据。

String value = new JWTUtil().verify(
        req.getHeader("token"),"userName")

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值