用户注册与登录(用户登录那点事儿)
用户注册与登录(用户登录那点事儿)什么是JWSJWT是JSON Web Token的简称,它是一种互联网开放标准。它被设计用来在两方之间传输声明(claims),在我们日常应用中,就是在服务器和客户端之间传递认证信息,也就是我们常说的token。在设计中,它被要求是结构紧凑,URL安全的,所以可以放在URL、请求头和body中。通常的做法是放在请求头的Authorization中,这也是很多第三方库采用的做法。JWT既可以是加密的也可以是不加密的,如果不加密的话,请不要放敏感信息。发生的事情是,浏览器把我输入的信息发送给了淘宝的服务器,来确定我是否输入了正确的账号密码,如果验证通过,服务器会发送一个凭证给浏览器,浏览器把它存起来,以后每次需要向服务器取数据都要带上这个凭证,这就像是人的身份证一样。好了,下面开始说点实在的。通常服务器返回的那个东西叫做sessionId,浏览器会把它存在cookie里,同时服务器上保存了我们
最近和同事一起打羽毛球总是感觉跟不上节奏,我思考再三后得出结论,一定是我的拍子不行,因为我的技术肯定是没有问题的。
OK,知道了原因之后我果断打开淘宝,搜索尤尼克斯,接着页面便出现了很多选择,我选择了林丹同款,点击之后跳出了一个登录页面。哈,原来我还没有登陆啊。
这简单,熟练地输入账号密码完成登录,接着页面出现了拍子的详细信息。好的,现在就让我来看看这块拍子都有什么特点……
现在让我们倒退,把画面定格在登录页面,当我的鼠标点击登录按钮后,都发生了什么。
发生的事情是,浏览器把我输入的信息发送给了淘宝的服务器,来确定我是否输入了正确的账号密码,如果验证通过,服务器会发送一个凭证给浏览器,浏览器把它存起来,以后每次需要向服务器取数据都要带上这个凭证,这就像是人的身份证一样。
好了,下面开始说点实在的。通常服务器返回的那个东西叫做sessionId,浏览器会把它存在cookie里,同时服务器上保存了我们的登录状态,但是需要sessionId这把钥匙才能获取。这样做的好处是,信息都存在服务器端,服务器可以掌控一切,比如它可以突然让我们强制退出登录。但缺点也是显而易见,服务器端的压力会增大,因为要使用很多内存来存储用户的登录状态。于此相对应的,还有一种方法是,把用户的登录状态存储在浏览器端,用数字签名的方式保证数据不被篡改,这时浏览器存储的就不是简单的sessionid了,而是具体的用户登录状态,比如用户的id。此时,服务器端只要验证浏览器传过来的凭证是否有效就可以了,它自己则不再存储用户的登录状态。到这,今天的主角就该出场了,它就是JWT,也就是存在浏览器中的那个东西,让我们看看它究竟长啥样。
PART01什么是JWT
JWT是JSON Web Token的简称,它是一种互联网开放标准。它被设计用来在两方之间传输声明(claims),在我们日常应用中,就是在服务器和客户端之间传递认证信息,也就是我们常说的token。在设计中,它被要求是结构紧凑,URL安全的,所以可以放在URL、请求头和body中。通常的做法是放在请求头的Authorization中,这也是很多第三方库采用的做法。JWT既可以是加密的也可以是不加密的,如果不加密的话,请不要放敏感信息。
PART 02什么是JWS
简单来说,JWT加签名就变成了JWS(json Web Signature),所以我们通常用的有签名的JWT其实准确的叫法是JWS。这里之所以提到JWS,是为了下面所涉及到的概念,通常我们不用深入了解,想要深入了解请参考RFC7515。
PART 03Payload
JWT的结构概括来说可以分成3部分,中间用(.)连接:
- Header
- Payload
- Signature
所以一个典型的jwt类似xxxxxx.yyyyyy.zzzzzz
Header
JWT的header是一个json对象,通常是下面这个样子:
{
"typ":"JWT"
"alg":"HS256"
}
typ属性表示这个令牌的类型,如果是JWT令牌,这个值是JWT。alg属性表示后面会用到的签名的算法,HS256表示HMAC SHA256。
一般情况下,有这两个属性就够了,但其实还可以有其它属性。实际上这两个属性是定义在JWS的header中的,JWT只是拿过来用。所以想知道header里还有哪些属性,请查看JWS的header属性,除此之外,payload中的属性也可以放到header中,特殊情况下有用。最后要把这个json使用base64url加密后,才能放到JWT中,作为JWT的第一部分。
Payload
JWT的payload部分也是一个json对象,JWT规定了7个字段供选用,分别是:
- iss(Issuer):签发人
- exp(Expiration Time):过期时间
- sub(Subject):主题
- aud(Audience):受众
- nbf(Not Before):生效时间
- iat(Issued At):签发时间
- jti(JWT ID):编号
以上这些属性都是可选的,除了这些,我们还可以自定义一些属性。下面是一个padyload的例子:
{
"iss":"http://localhost"
"iat":1661503024
"exp":1661506624
"nbf":1661503024
"jti":"jloZNwoyTlIW3OE2"
"sub":1
"prv":"23bd5c8949f600adb39e701c400872db7a5976f7"
}
和header一样,最后用base64url加密后放到JWT的第二部分。
需要注意的是,如果加了签名,那么这部分信息确实无法被更改了,但是依然可以被任何人看到,所以敏感信息不要放到paylaod中,加密过的信息除外。
Signature
Signature是对前面2部分的签名,目的是防止数据被篡改。首先我们需要一个密钥,这个密钥放在服务器端,然后使用Header里指定的算法(通常是HS256),按照下面的规则生成签名:
HMACSHA256(base64UrlEncode(header) "." base64UrlEncode(payload) secret)
把这个签名也用base64url加密,然后放到JWT的第三部分,一个完整的JWT就生成了。
PART 04base64Url
由于JWT有可能被放到url中,所以这里对Header和Payload的加密不是普通的base64算法,而是在此基础上做了一些修改。首先依然是用普通的base64算法对字符串加密,然后把加密的字符串中的" "替换成"-","/"替换成"_",最后去掉字符串中的"="。
PART 05JWT的结构
1. JWT是无状态的,所以服务器不会保存用户的登录信息,这可以减轻服务器端的压力
2. 用户先在设备A进行登录,后又在设备B进行登录,此时A设备的登录状态不会退出。
3. JWT一旦签发,除非过期或者更换了密钥,否者一直有效,正因如此,JWT的过期时间最好不要太长。
以上,JWT的重点内容都在这里了,虽然不多但是要理解其中任何一个细节都不是容易的事,如果你觉得我讲得还不错,就给我点个赞吧。最后祝所有看完这篇文章的朋友都能实现自己的理想,事业有成,家庭幸福。
本文所有文字版权均属“宝略科技”,更多内容请搜索关注【宝略科技】微信公众号~