菜菜,上次你讲的cookie和session认证方式,我此次面试果真遇到了web
结果怎么样?面试
结果面试官问我还有没有更好的方式?算法
看来你又挂了apache
别说了,伤心呀。到底还有没有更好的方式呢?json
你猜?后端
经过上一篇你大致已经了解session和cookie认证了,session认证须要服务端作大量的工做来保证session信息的一致性以及session的存储,因此现代的web应用在认证的解决方案上更倾向于客户端方向,cookie认证是基于客户端方式的,可是cookie缺点也很明显,到底有哪些缺点能够跳转上一次的文章。那有没有一种比较折中的方案呢?有的跨域
把认证信息保存在客户端,关键点就是安全的验证,若是能解决认证信息的安全性问题,彻底能够把认证信息保存在客户端,服务端彻底无认证状态,这样的话服务端扩展起来要方便不少。关于信息的安全解决方案,如今广泛的作法就是签名机制,像微信公众接口的验证方式就基于签名机制。安全
签名,就是只有信息的发送者才能产生的别人没法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证实。服务器
当用户成功登录系统并成功验证有效以后,服务器会利用某种机制产生一个token字符串,这个token中能够包含不少信息,例如来源IP,过时时间,用户信息等, 把这个字符串下发给客户端,客户端在以后的每次请求中都携带着这个token,携带方式其实很自由,不管是cookie方式仍是其余方式均可以,可是必须和服务端协商一致才能够。固然这里我不推荐cookie。当服务端收到请求,取出token进行验证(能够验证来源ip,过时时间等信息),若是合法则容许进行操做。微信
基于token的验证方式也是现代互联网普通使用的认证方式,那它有什么优势吗?
1. 支持跨域访问,Cookie是不容许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息经过HTTP头传输.
2. 无状态:Token机制在服务端不须要存储session信息,由于Token自身包含了全部登陆用户的信息,只须要在客户端的cookie或本地介质存储状态信息.
3. 解耦 不须要绑定到一个特定的身份验证方案。Token能够在任何地方生成,只要在你的API被调用的时候,你能够进行Token生成调用便可.
4. 适用性更广:只要是支持http协议的客户端,就可使用token认证。
5. 服务端只须要验证token的安全,没必要再去获取登陆用户信息,由于用户的登陆信息已经在token信息中。
6. 基于标准化:你的API能够采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python,PHP)和多家公司的支持(如:Firebase,Google, Microsoft).
那基于token的认证方式有哪些缺点呢?
1. 网络传输的数据量增大:因为token中存储了大量的用户和安全相关的信息,因此比单纯的cookie信息要大不少,传输过程当中须要消耗更多流量,占用更多带宽,
2. 和全部的客户端认证方式同样,若是想要在服务端控制token的注销有难度,并且也很难解决客户端的劫持问题。
3. 因为token信息在服务端增长了一次验证数据完整性的操做,因此比session的认证方式增长了cpu的开销。
可是总体来看,基于token的认证方式仍是比session和cookie方式要有很大优点。在所知的token认证中,jwt是一种优秀的解决方案
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于做为JSON对象在各方之间安全地传输信息。该信息能够被验证和信任,由于它是数字签名的。
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
头部
header典型的由两部分组成:token的类型(“JWT”)和算法名称(好比:HMAC SHA256或者RSA等等)。
{
"alg": "HS256",
"typ": "JWT"
}
Payload
Payload 部分也是一个JSON对象,用来存放实际须要传递的数据。JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过时时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
除了以上字段以外,你彻底能够添加本身想要的任何字段,这里仍是提醒一下,因为jwt的标准,信息是不加密的,因此一些敏感信息最好不要添加到json里面
{
"Name":"菜菜",
"Age":18
}
Signature
为了获得签名部分,你必须有编码过的header、编码过的payload、一个秘钥(这个秘钥只有服务端知道),签名算法是header中指定的那个,然对它们签名便可。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
算出签名之后,把 Header、Payload、Signature 三个部分拼成一个字符串,每一个部分之间用"点"(.)分隔,就能够返回给用户。须要提醒一下:base64是一种编码方式,并不是加密方式。
基于token的认证方式,大致流程为:
1. 客户端携带用户的登陆凭证(通常为用户名密码)提交请求
2. 服务端收到登陆请求,验证凭证正确性,若是正确则按照协议规定生成token信息,通过签名并返回给客户端
3. 客户端收到token信息,能够保存在cookie或者其余地方,之后每次请求的时候都携带上token信息
4. 业务服务器收到请求,验证token的正确性,若是正确则进行下一步操做
这里再重复一次,不管是token认证,cookie认证,仍是session认证,一旦别人拿到客户端的标识,仍是能够伪造操做。因此采用任何一种认证方式的时候请考虑加入来源ip或者白名单,过时时间,另外有条件的状况下必定要使用https。