随着互联网的不断发展,不管是网站仍是app,通常都会要求用户注册/登陆。主要的登陆方式有帐户密码登陆、第三方登陆(微信登陆、QQ登陆、微博登陆等)
登陆可分为三个阶段(登陆验证、登陆持续、退出登陆);登陆验证
指客户端提供帐号/密码(或第三方平台(微信、qq)获取openid/unionid)向服务器提出登陆请求,服务器应答请求判断可否登陆并返回相应数据;登陆持续
指客户端登陆后, 服务器可以分辨出已登陆的客户端,并为其持续提供登陆权限的服务器。退出登陆
指客户端退出登陆状态。前端
因为HTTP是一种无状态的协议
,服务器单从网络链接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,不管谁访问都必须携带本身通行证web
方案:客户端登陆成功后, 服务器为其分配一个惟一的凭证, 客户端每次请求资源时都带上这个凭证;
实现方案面试
Cookie
其实是一小段的文本信息
。客户端请求服务器,若是服务器须要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来
。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还能够根据须要修改Cookie的内容。redis
cookie实际上是补充http协议的无状态性的缺点,底层是经过服务器端在http响应消息中增长set-cookie
字段来将cookie信息发送给浏览器端,由于它只能存4k,通常用来存浏览器的身份信息,浏览器在访问服务器的某些资源的时候,会在http请求头中将cookie数据传给服务器,这样服务器就知道是谁请求的了,可是若是用户清除了cookie,那就啥都没有了算法
一、Expires:该Cookie失效的时间,单位秒。数据库
二、Domain:
咱们如今有二个域名。域名A:b.f.com,域名B:d.f.com;显然域名A和域名B都是f.com的子域名后端
封装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
由于Cookie是存储在客户端,用户能够随意修改。因此,存在必定的安全隐患。
防篡改签名:服务器为每一个Cookie项生成签名。若是用户篡改Cookie,则与签名没法对应上。以此,来判断数据是否被篡改。
原理以下:缓存
举个栗子:
好比服务器接收到请求中的Cookie项username=pony|34Yult8i,而后使用签名生成算法secret(pony)=666。 算法获得的签名666和请求中数据的签名不一致,则证实数据被篡改。安全
session是一种服务器机制,是存储在服务器上的信息,主要配合cookie完成浏览器的身份认证和状态存储方式多种多样,能够是服务器的内存中,或者是mongo数据库,redis内存数据库中。为了得到更高的存取速度,服务器通常把Session放在内存里。每一个用户都会有一个独立的Session。若是Session内容过于复杂,当大量客户访问服务器时可能会致使内存溢出。所以,Session里的信息应该尽可能精简。
Session相对于cookie较安全点,当用户请求服务器的时候,服务器会把数据临时存下来,若是退出网站后,session会被销毁。
Session
是基于cookie
实现的,浏览器第一次访问服务器时,服务器建立一个Session
,同时生成一个惟一的会话key
,即sessionID
。接着sessionID
及session
分别做为key
和value
保存到缓存中,也能够保存到数据库中,而后服务器把sessionID
经过set-cookie
的方式写入浏览器,浏览器下次访问服务器时直接携带上cookie
中的sessionID
,服务器再根据sessionID
找到对应的session
进行匹配,来判断用户是否登陆
【1】 客户端发起登陆请求,服务器端建立session,并经过set-cookie将生成的sessionID写入的客户端的cookie中。
【2】 在发起其余须要权限的接口的时候,客户端的请求体的Header部分会携带sessionID发送给服务端。而后根据这个sessionId去找服务器端保存的该客户端的session,而后判断该请求是否合法。
token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户惟一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成必定长的十六进制字符串,能够防止恶意第三方拼接token请求服务器)。还能够把不变的参数也放进token,避免屡次查库
浏览器第一次访问服务器,根据传过来的惟一标识userId,服务端会经过一些算法,如经常使用的HMAC-SHA256算法,而后加一个密钥,生成一个token,而后经过BASE64编码一下以后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,而后会用相同的算法和密钥去验证token,若是经过,执行业务操做,不经过,返回不经过信息;
浏览器第一次访问服务器时,服务器根据传过来的惟一标识userId,经过一些算法,加一个密钥,生成一个token,接着经过base64编码将token返回给客户端。客户端将token保存起来,下次请求时须要带着token,服务器收到请求后,用相同的算法和密钥去验证token
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入库)
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也可直接被用于认证,也可被加密。
若是你以为这篇文章对你有所帮助,那就顺便点个赞吧,点点关注不迷路~
黑芝麻哇,白芝麻发,黑芝麻白芝麻哇发哈!
前端哇发哈