基于JWT的身份验证
Posted So istes immer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于JWT的身份验证相关的知识,希望对你有一定的参考价值。
JWT(JSON Web Token)是目前最流行的跨域认证解决方案
1.跨域认证的问题
互联网服务中的用户认证流程:
1.用户向服务器发送用户名和密码
2.服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等
3.服务器向用户返回一个session_id,写入用户的Cookie
4.用户随后的每一次请求,都会通过Cookie将session_id传回服务器
5.服务器收到session_id,找到前期保存的数据,由此得知用户的身份
该模式的缺点在于,扩展性(scaling)不好。单机没问题,如果是服务器集群或者是跨域的服务导向架构,就要求session数据共享,每台服务器都能够读取session
举例:
A网站和B网站是用一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问如何实现?
解决方案①:session数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。优点:架构清晰。缺点:工程量比较大,并且万一持久层挂了,就会单点失败。
解决方案②:服务器索性不保存session数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT就是这种方案的一个代表。
2.JWT原理
服务器认证之后,生成一个JSON对象,发回给用户。以后,用户与服务器通信的时候,都要发回这个JSON对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器再生成这个对象的时候,会加上签名。
服务器就不保存任何session数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。
3.JWT的数据结构
实际的JWT是一个很长的字符串,中间用点(.)分隔成三个部分。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT的三个部分:Header(头部).Payload(负载).Signature(签名)
测试JWT网站:https://jwt.io/
Header
Header部分是一个JSON对象,描述JWT的元数据,如下
{
"alg": "HS256", //表示签名的算法
"typ": "JWT" //表示token的type,JWT令牌的type就是JWT
}
将该JSON对象用Base64URL算法转成字符串
Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段
iss(issuer): 签发人
exp(expiration time):过期时间
sub(subject):主题
aud(audience): 受众
nbf(Not Before): 生效时间
iat(Issued At): 签发时间
iti(JWT ID):编号
除了官方字段,也可以自定义私有字段,但是不要把私密信息放在这个部分,因为JWT默认不加密
这个JSON对象也要使用Base64URL算法转成字符串
Signature
Signature部分是对前两部分的签名,防止数据篡改
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后使用Header里面
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
算出签名之后,将Header、Payload、Signature三个部分拼成一个字符串,每个部分用“点”分隔,就可以返回给用户。
在JWT中,消息体是透明的,使用签名可以保证消息不被篡改。但不能实现数据加密功能。
Base64URL算法和Base64算法差不多。
4.JWT的使用方式
客户端收到服务器返回的JWT,可以存储在Cookie里面,也可以存储在localStorage
此后,客户端每次与服务器通信,都要带上这个JWT。你可以把它放在Cookie里面自动发送,但是这样不能跨域,所以更好的做法是放在HTTP请求的头信息Authorization字段里面。
另一种做法是跨域的时候,JWT就放在POST请求的数据体里面。
JWT的最大缺点是,由于服务器不保存session状态,因此无法在使用过程中废止某个token,或者更改token的权限。也就是说一旦JWT签发了,在到期之前就会始终有效。
什么是跨域?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
域名:
主域名不同 http://www.baidu.com/index.html -->http://www.sina.com/test.js
子域名不同 http://www.666.baidu.com/index.html -->http://www.555.baidu.com/test.js
域名和域名ip http://www.baidu.com/index.html -->http://180.149.132.47/test.js
端口:
http://www.baidu.com:8080/index.html–> http://www.baidu.com:8081/test.js
协议:
http://www.baidu.com:8080/index.html–> https://www.baidu.com:8080/test.js
备注:
1、端口和协议的不同,只能通过后台来解决
2、localhost和127.0.0.1虽然都指向本机,但也属于跨域
在Node.js中使用JWT https://github.com/auth0/node-jsonwebtoken
以上是关于基于JWT的身份验证的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 2 上实现基于过滤器的 JWT 身份验证与 OAuth2 JWT 身份验证