使用JSON-WEB-TOKENS方式认证用户登录

JWT产生缘由:
传统的把token存在session中太消耗服务端的资源,特别是在用户量大的时候,这是一笔不少的资源开销。为了解决这个问题,JWT就产生了。使用JWT可以把token分散用户自己的客户端上,从而减少服务端的开销。

JWT是什么?
JWT是json web token.它定义了一种简洁的、安全的、用户通讯双方通讯的数据格式。
JWT的组成,由3部分组成:
①、Header(头部),包含两个部分,token类型和采用的算法。
{
"alg": "HS256",
"typ": "JWT"
}
②、payload(负载),存放一些公开的信息,存放信息是为了防止多次查库,存放公开的信息是因为这部分是公开的,别人可以看到。通常包含以下几部分(还可以指定其他的):
{
"iss": "lion1ou JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
}
iss:签发者
iat:签发时间
exp:过期时间
aud:接收方
sub:面向的用户
③、Signature (签名)
顾名思义,存放的就是签名。这个签名是这样来的:把①②部分使用base64编码,再使用我们自己的一个**,然后使用header中指定的签名算法(这里指定的是HS256)进行签名。

3部分通过点连接在一起,比如一个JWT:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

签名的作用:
保证JWT没有被篡改过。

验证的时候是这样验证:
拿到一串JWT之后,base64解码码第一部分,获取加密方法(如HS256),根据第一二部分和我们对应的**,再签因一次名,得到的新签名与JWT的第三部分对比,如果一致的,则没有被篡改过;如果不一致,则被篡改过了。

验证的目的:
因为第一二部分是可以解码得回明文信息的。那么不怀好意的人就可以先篡改第一二部分,然后再用base64编码,加上原先的签名或者再伪造一个签名组成一个新的比且被篡改过的JWT,发到服务端。无论是用原先的签名或是再伪造一个签名,都是无法通过服务端的验证的,因为签名会随着第一二部分改变而改变。

信息暴露问题:
在这里大家一定会问一个问题:Base64是一种编码,是可逆的,那么我的信息不就被暴露了吗?
是的。所以,在JWT中,不应该在负载里面加入任何敏感的数据。在有些例子中,传输的是用户的User ID。这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。但是像密码这样的内容就不能被放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。因此JWT适合用于向Web应用传递一些非敏感信息。

JWT可以使用两种解密算法进行加密:HMAC 算法或者RSA 的公钥**对。

用户登录认证流程:
使用JSON-WEB-TOKENS方式认证用户登录

和Session方式存储id的差异
Session方式存储用户id的最大弊病在于Session是存储在服务器端的,所以需要占用大量服务器内存,对于较大型应用而言可能还要保存许多的状态。一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存储。
而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。除了用户id之外,还可以存储其他的和用户相关的信息,例如该用户是否是管理员、用户所在的分组等。虽说JWT方式让服务器有一些计算压力(例如加密、编码和解码),但是这些压力相比磁盘存储而言可能就不算什么了。具体是否采用,需要在不同场景下用数据说话。
  • 单点登录
Session方式来存储用户id,一开始用户的Session只会存储在一台服务器上。对于有多个子域名的站点,每个子域名至少会对应一台不同的服务器,例如:www.taobao.comnv.taobao.comnz.taobao.comlogin.taobao.com。所以如果要实现在login.taobao.com登录后,在其他的子域名下依然可以取到Session,这要求我们在多台服务器上同步Session。使用JWT的方式则没有这个问题的存在,因为用户的状态已经被传送到了客户端。
总结
JWT的主要作用在于(一)可附带用户信息,后端直接通过JWT获取相关信息。(二)使用本地保存,通过HTTP Header中的Authorization位提交验证。但其实关于JWT存放到哪里一直有很多讨论,有人说存放到本地存储,有人说存 cookie。个人偏向于放在本地存储,如果你有什么意见和看法欢迎提出。