JWT是目前最流行的跨域认证解决方案。
一、跨域认证的问题
session登录认证方案:用户从客户端传递用户名、密码等信息,服务端认证后将信息存储在session中,将session_id放到cookie中。 以后访问其他页面,自动从cookie中取到session_id,再从session中取认证信息。
另一类解决方案,将认证信息,返回给客户端,存储到客户端。下次访问其他页面,需要从客户端传递认证信息回服务端。 JWT就是这类方案的代表,将认证信息保存在客户端。
扫盲3答
1.ajax会自动带上同源的cookie,不会带上不同源的cookie
2. 可以通过前端设置withCredentials为true, 后端设置Header的方式让ajax自动带上不同源的cookie,但是这个属性对同源请求没有任何影响。会被自动忽略。
3. 这是MDN对withCredentials的解释: MDN-withCredentials ,我接着解释一下同源。
众所周知,ajax请求是有同源策略的,虽然可以应用CORS等手段来实现跨域,但是这并不是说这样就是“同源”了。ajax在请求时就会因为这个同源的问题而决定是否带上cookie,这样解释应该没有问题了吧,还不知道同源策略的,应该去谷歌一下看看。
互联网服务器离不开用户认证。一般流程是下面这样。
- 1、用户向服务器发送用户名和密码。
- 2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用
户角色、登录时间等等。 - 3、服务器向用户返回一个 session_id ,写入用户的Cookie 。
- 4、用户随后的每一个请求,都会通过Cookie,将session_id 传回服务
器。 - 5、服务器收到session_id,找到前期保存的数据,由此得知用户的身份。
这种模式的问题在于,扩展性不好。单机当然没问题,如果是服务器集群,或者是跨域的服务导向架构,就要求session数据共享,每台服务器都能够读取session。
举例来说,A网站和B网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登陆,请问怎么实现?
一种解决方案是session数据持久化,写入数据库或者别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。
另一种解决方案是服务器索性不保存session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT就是这种方案的一个代表。
二、JWT 的原理
JWT 的原理是,服务器认证后,生成一个JSON对象,发给用户,就像下面这样。
{
"姓名":"大根",
"角色":"Store",
"过期时间":"xxx"
}
以后,用户与服务端通信的时候,都要发回这个Json 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。
服务器就不保存任何session数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。
三、JWT 的数据结构
实际的 JWT 大概就像下面这样。
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJVVU1TIiwiYXVkIjpbInBheS1tYWluIiwicGF5LWFwaSIsImdlbmVyaWMiXSwidXNlcl9uYW1lIjoieHlwYXkiLCJzY29wZSI6WyJtZ3IiXSwiaWQiOjIsImV4cCI6MTU2ODI5NzY0OSwiYXV0aG9yaXRpZXMiOlsiUk9MRV9QUk9NT1RFUiJdLCJqdGkiOiIwMDUwMzg2OC05NDEzLTQ4ZmMtYWIzMS1hNmU2NWYzNzczMDgiLCJjbGllbnRfaWQiOiJwYXltZ3IifQ
.fxPGUadRyU8Q7VANZ6Wd68s47aOV9eiejetH0xs1x0r3862R5QJU54aoEwc-xXHmNTgsSaIoyxLjKSGZIEZDFPGFG-EzSl1XIW6mbdreLCRtuN3ECVul2WxDVEV4kLeFzVPUl302TN-OhjbJKF1VKnIAvlIadBf5DWiWnKDaLFw9vgVLe9hgV5UH15x910dQvjbUGwtknlZusFOS9PBWEe6gR83GAFYCEgN4pRIR7eEUn9G-pjT-OjZB-y1g9I9ditob3i8GAMg5bzGUzftm11EOaA7LsOEghkEFZkquFJfieaLmYlbCEzyk9GyIvODQJKIqBCg4aCqEC5Cy_sVz4g
它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。
JWT 的三个部分依次如下。
写成一行,就是下面的样子。
Header.Payload.Signature