【同源问题】
浏览器安全的基石是"同源政策"(same-origin policy)。很多开发者都知道这一点,但了解得不全面。1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。
-
协议相同
-
域名相同
-
端口相同
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
【Cookie】
Http是无状态的协议,客户端每次对服务端的http请求都是独立的,不受该客户端其它的请求的影响。为了把Http这个无状态协议变的与上下文有关系,我们引入了会话Session的概念,具有相同会话ID的请求使之变成了有状态。cookie是一个存储在客户端的字符串属性,可以用它对当前网页的cookie进行读,写,增.删等操作;javascript能够用document对象的cookie属性对cookie进行操作;
可以简单的理解为我们访问的地址(请注意不是真正映射成的IP地址),而Cookie具有不跨域性质,只会将属于该域名的Cookie信息添加到Header中传到Server端。
【比如说】我们请求<https://www.google.com/>时,浏览器会自动把google.com的Cookie带过去给google的服务器,而不会把<https://www.baidu.com/>的Cookie带过去给google的服务器。
这就意味着,由于域名不同,用户向系统A登录后,系统A返回给浏览器的Cookie,用户再请求系统B的时候不会将系统A的Cookie带过去。
针对Cookie存在跨域问题,有几种解决方案:
-
服务端将Cookie写到客户端后,客户端对Cookie进行解析,将Token解析出来,此后请求都把这个Token带上就行了
-
多个域名共享Cookie,在写到客户端的时候设置Cookie的domain。
-
将Token保存在SessionStroage中(不依赖Cookie就没有跨域的问题了)
【Token】
-
客户端使用用户名和密码请求登录
-
服务端收到请求,验证用户名和密码
-
验证成功后,服务端会签发一个token,再把这个token返回给客户端
-
客户端收到token后可以把它存储起来,比如放到cookie中
-
客户端每次向服务端请求资源时需要携带服务端签发的token,可以在cookie或者header中携带
-
服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求数据
这种基于token的认证方式相比传统的session认证方式更节约服务器资源,并且对移动端和分布式更加友好。其优点如下:
-
支持跨域访问:cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题
-
无状态:token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力
-
更适用CDN:可以通过内容分发网络请求服务端的所有资料
-
更适用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多
-
无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御
通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token
,并且这个JWT token
带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。JWT的认证流程如下:
-
首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探
-
后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串header,payload,signature
-
后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
-
前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
-
后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等
-
验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果
【JWT认证的优势】
对比传统的session认证方式,JWT的优势是:
-
简洁:JWT Token数据量小,传输速度也很快
-
因为JWT Token是以JSON加密形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持
-
不需要在服务端保存会话信息,也就是说不依赖于cookie和session,所以没有了传统session认证的弊端,特别适用于分布式微服务
-
单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话, token可以被保存在客户端的任意位置的内存中,不一定是cookie,所以不依赖cookie,不会存在这些问题
-
适合移动端应用:使用Session进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到Cookie(需要 Cookie 保存 SessionId),所以不适合移动端
-
因为这些优势,目前无论单体应用还是分布式应用,都更加推荐用JWT token