大话javascript 7期:Cookie、Session和Token的那些事儿

1、登陆认证机制

随着互联网的不断发展,不管是网站仍是app,通常都会要求用户注册/登陆。主要的登陆方式有帐户密码登陆、第三方登陆(微信登陆、QQ登陆、微博登陆等)

登陆可分为三个阶段(登陆验证、登陆持续、退出登陆);
登陆验证指客户端提供帐号/密码(或第三方平台(微信、qq)获取openid/unionid)向服务器提出登陆请求,服务器应答请求判断可否登陆并返回相应数据;
登陆持续指客户端登陆后, 服务器可以分辨出已登陆的客户端,并为其持续提供登陆权限的服务器。
退出登陆指客户端退出登陆状态。前端

2、保持登陆持续状态的实现方式

为何要保持登陆状态的持续?

因为HTTP是一种无状态的协议,服务器单从网络链接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,不管谁访问都必须携带本身通行证web

方案:客户端登陆成功后, 服务器为其分配一个惟一的凭证, 客户端每次请求资源时都带上这个凭证;

实现方案面试

  1. cookie 会话机制
  2. session 会话机制
  3. token 会话机制

3、Cookie、Session和Token

Cookie(浏览器缓存)

1.什么是Cookie

Cookie其实是一小段的文本信息。客户端请求服务器,若是服务器须要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还能够根据须要修改Cookie的内容。redis

clipboard.png

cookie实际上是补充http协议的无状态性的缺点,底层是经过服务器端在http响应消息中增长set-cookie字段来将cookie信息发送给浏览器端,由于它只能存4k,通常用来存浏览器的身份信息,浏览器在访问服务器的某些资源的时候,会在http请求头中将cookie数据传给服务器,这样服务器就知道是谁请求的了,可是若是用户清除了cookie,那就啥都没有了算法

2.Cookie的属性

clipboard.png

clipboard.png

一、Expires:该Cookie失效的时间,单位秒。数据库

  • 若是为正数,则该Cookie在maxAge秒以后失效(持久级别Cookie)。
  • 若是为负数,该Cookie为临时Cookie,关闭浏览器即失效(会话级别Cookie),浏览器也不会以任何形式保存该Cookie。
  • 若是为0,表示删除该Cookie。默认为–1;

二、Domain:
咱们如今有二个域名。域名A:b.f.com,域名B:d.f.com;显然域名A和域名B都是f.com的子域名后端

  • 若是咱们在域名A中的Cookie的domain设置为.f.com,那么.f.com及其子域名均可以获取这个Cookie,即域名A和域名B均可以获取这个Cookie
  • 若是域名A没有显式设置Cookie的domain方法,那么domain就为.b.f.com,不同的是,这时,域名A的子域名将没法获取这个Cookie
  • HttpOnly: 这个属性是面试的时候常考的,若是这个属性设置为true,就不能经过js脚原本获取cookie的值,能有效的防止xss攻击

3.Cookie的操做

封装cookie的经常使用操做方法浏览器

  • 设置cookie
  • 读取cookie
  • 删除cookie
var cookieUtil = {
    getItem: function (name) {
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;
        if (cookieStart > -1) {
            var cookieEnd = document.cookie.indexOf(';', cookieStart);
            if (cookieEnd == 1) {
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd))
        }
        return cookieValue;
    },
    setItem: function (name, value, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
        if (expires) {
            cookieText += ";expires=" + expires.toGMTString();
        }
        if (path) {
            cookieText += ";path=" + path;
        }
        if (domain) {
            cookieText += ";domain=" + domain;
        }
        if (secure) {
            cookieText += ";secure";
        }
        document.cookie = cookieText;
    },
    unset: function (name, path, domain, secure) {
        this.setItem(name, "", new Date(0), path, domain, secure)
    }
}
CookieUtil.setItem("name", 'tom'); // 设置cookie
console.log(CookieUtil.getItem('name'));//读取cookie
CookieUtil.unset("name")//删除cookie

4.Cookie防篡改机制

由于Cookie是存储在客户端,用户能够随意修改。因此,存在必定的安全隐患。
防篡改签名:服务器为每一个Cookie项生成签名。若是用户篡改Cookie,则与签名没法对应上。以此,来判断数据是否被篡改。

原理以下:缓存

  • 服务端提供一个签名生成算法secret
  • 根据方法生成签名secret(wall)=34Yult8i
  • 将生成的签名放入对应的Cookie项username=wall|34Yult8i。其中,内容和签名用|隔开。
  • 服务端根据接收到的内容和签名,校验内容是否被篡改。

举个栗子:
好比服务器接收到请求中的Cookie项username=pony|34Yult8i,而后使用签名生成算法secret(pony)=666。 算法获得的签名666和请求中数据的签名不一致,则证实数据被篡改。安全

Session(会话)

1.什么是session

session是一种服务器机制,是存储在服务器上的信息,主要配合cookie完成浏览器的身份认证和状态存储方式多种多样,能够是服务器的内存中,或者是mongo数据库,redis内存数据库中。为了得到更高的存取速度,服务器通常把Session放在内存里。每一个用户都会有一个独立的Session。若是Session内容过于复杂,当大量客户访问服务器时可能会致使内存溢出。所以,Session里的信息应该尽可能精简。

Session相对于cookie较安全点,当用户请求服务器的时候,服务器会把数据临时存下来,若是退出网站后,session会被销毁。

Session是基于cookie实现的,浏览器第一次访问服务器时,服务器建立一个Session,同时生成一个惟一的会话key,即sessionID。接着sessionIDsession分别做为keyvalue保存到缓存中,也能够保存到数据库中,而后服务器把sessionID经过set-cookie的方式写入浏览器,浏览器下次访问服务器时直接携带上cookie中的sessionID,服务器再根据sessionID找到对应的session进行匹配,来判断用户是否登陆

2.session鉴权过程

【1】 客户端发起登陆请求,服务器端建立session,并经过set-cookie将生成的sessionID写入的客户端的cookie中。
【2】 在发起其余须要权限的接口的时候,客户端的请求体的Header部分会携带sessionID发送给服务端。而后根据这个sessionId去找服务器端保存的该客户端的session,而后判断该请求是否合法。

3.cookie和session的区别

clipboard.png

Token(身份令牌)

1.什么是token

token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户惟一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成必定长的十六进制字符串,能够防止恶意第三方拼接token请求服务器)。还能够把不变的参数也放进token,避免屡次查库

浏览器第一次访问服务器,根据传过来的惟一标识userId,服务端会经过一些算法,如经常使用的HMAC-SHA256算法,而后加一个密钥,生成一个token,而后经过BASE64编码一下以后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,而后会用相同的算法和密钥去验证token,若是经过,执行业务操做,不经过,返回不经过信息;

2.token生成方式

浏览器第一次访问服务器时,服务器根据传过来的惟一标识userId,经过一些算法,加一个密钥,生成一个token,接着经过base64编码将token返回给客户端。客户端将token保存起来,下次请求时须要带着token,服务器收到请求后,用相同的算法和密钥去验证token

3.token和session的区别

token和session其实都是为了身份验证,session通常翻译为会话,而token更多的时候是翻译为令牌;
session服务器会保存一份,可能保存到缓存,文件,数据库;一样,session和token都是有过时时间一说,都须要去管理过时时间;
其实token与session的问题是一种时间与空间的博弈问题,session是空间换时间,而token是时间换空间。二者的选择要看具体状况而定。
虽然确实都是“客户端记录,每次访问携带”,但 token 很容易设计为自包含的,也就是说,后端不须要记录什么东西,每次一个无状态请求,每次解密验证,每次当场得出合法 /非法的结论。这一切判断依据,除了固化在 CS 两端的一些逻辑以外,整个信息是自包含的。这才是真正的无状态。
而 sessionid ,通常都是一段随机字符串,须要到后端去检索 id 的有效性。万一服务器重启致使内存里的 session 没了呢?万一 redis 服务器挂了呢?

sessionID是基于cookie实现的,而token不须要基于cookie。这就致使了sessionID只能用在浏览器上,对于原生的应用没法实现。原生的应用是不具有cookie的特性的。另外sessionID能够实现服务端注销会话,而token不能(固然你能够把用户登录的token存入到redis中,可是不推荐token入库)

4.token的优势

Token做为用户认证的处理方式,有几个优势:

  • 无状态,可扩展:不会在服务端存储用户的登陆状态,能够很容易的实现服务器的增减
  • 支持移动设备,对多类型客户端的支持良好
  • 支持跨程序调用,各个接口之间的调用更方便
  • 安全可靠

5.什么是JSON Web Token

JSON web Token,简称JWT,本质是一个token,是一种紧凑的URL安全方法,用于在网络通讯的双方之间传递。通常放在HTTP的headers参数里面的authorization里面,值的前面加Bearer关键字和空格。除此以外,也能够在url和request body中传递。

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明通常被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也能够增长一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

若是你以为这篇文章对你有所帮助,那就顺便点个赞吧,点点关注不迷路~

黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈!

前端哇发哈

相关文章
相关标签/搜索