Cookie + Session
客户端第一次请求服务器,服务端会创建Session,返回SessionId,通过
Set-Cookie
响应将其保存至Cookie中,客户端第二次请求,服务端解析Cookie中的SessionId,可以获取Session。
优点
*:
Cookie可以设置
http-only
属性,设置该属性后将无法通过js脚本读取,能够有效避免XSS攻击;
开箱即用,不需要在客户端实现API。
Cookie会与特定的域名绑定,所以跨域访问需要配置反向代理;
容易导致CSRF/XSRF即跨站请求伪造攻击;
以Java Web程序为例,session中会存储用户信息,假设用户首先登陆了一个受信任的网站A,cookie信息中将会存储会话sessionid,此时不关闭A,继续访问某钓鱼网站B,若B中存在图片
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
,点击图片之后将会跳转访问A网站,此时对A网站的session未被销毁,cookie也存在,所以A网站会认为仍然是用户操作,这样钓鱼网站B就达到了模拟用户操作的目的。
每次请求都会发送该信息,即使该请求不需要进行验证;
Cookie+Session中,用户验证时一般会在Session中存储用户信息,不安全。
Token
客户端请求,服务端根据用户信息创建Token,响应给客户端,客户端保存Token至Cookie/SessionLocalStorage/LocalStorage等存储空间中,客户端第二次请求,将Token放置在请求头中(规范,其实不放在请求头也可以),服务端拦截请求,获取Token并验证。
可以只验证想要验证的请求;
免疫CSRF/XSRF攻击;
可以跨域共享,Token可以被发送至多个服务端,因此,域名myapp.com上的一个web应用程序可以同时向myservice1.com和myservice2.com发送授权请求;
Token仅仅是个令牌,不会存储用户信息。
必须手动将Token存储到一个地方,而SessionId则会自动存储到Cookie中,常用存储位置:
LocalStorage
缺点:即使关闭了浏览器窗口,token依然存在;
SessionStorage
优点:关闭浏览器窗口后,token即消失;
缺点:登录验证后,打开一个新的选项卡,仍然需要验证,即每个窗口存在自己的
SessionStorage
Cookie
优点:默认情况下,关闭浏览器窗口后,token即消失;
缺点:每次请求,Cookie都会被发送。
注意,Cookie只是个存储空间,可以用于存储Sessionid或Token。只不过一般SessionId使用Cookie进行存储,token使用LocalStorage进行存储。