JWT之:常见的认证机制
首先说明一下什么是认证:
认证其实就是登录,只不过官方的叫法为认证,这个不用太过纠结。
那么我们常见的认证机制都有哪些呢?
这里我总结了几个。
1:HTTP Basic Auth (这种是非常古老的,现在几乎没人用了)
它的逻辑是:每次一过来访问,都得带上你自己的用户名和密码这两个参数。
这种是傻瓜式的验证,操作很明显,效率很低。
但是,虽然他的效率很低,但是注意:它是无状态的,
虽然他很垃圾,但是它的思想很先进,无状态的这个思想很重要。
我们项目追求的就是无状态。
官方文档:
HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,
简言之,Basic Auth是配合RESTful API 使用的最简单的认证方式,只需提供用户名密码即可,
但由于有把用户名密码暴露给第三方客户端的风险,在生产环境下被使用的越来越少。
因此,在开发对外开放的RESTful API时,尽量避免采用HTTP BasicAuth。
不建议使用,过时。
说明一点:可能有的人不清楚有状态和无状态的区别:
简单理解:
有状态:就是你的服务器,要保存登录信息
无状态:不用存
因为这个不好用,后来就出了下面这个
2:Cookie Auth (就是我们常用的cookie)
它的逻辑是:要把登录的信息在浏览器端存到cookie中,服务器端存到session中。
然后cookie和session能对上,就认为你是登录的。
这种方式比前一个稍微有点复杂,服务端和客户端都存了用户的登录信息,得保存。
而且它依赖于cookie。
因为cookie我们知道它是个双刃剑。
首先:cookie能帮我们简化很多操作,但随之而来的就是它不安全。
其次:cookie还有另外一个不好的地方就是,他的局限性很强。
就是它只局限于浏览器,像android和ios等其他移动端就不适用了。
所以,这种cookie的认证方式,现在也不怎么用。
尤其在分布式项目尤为不适用。
官方文档:
Cookie认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象;
通过客户端带上来Cookie对象来与服务器端的session对象匹配来实现状态管理的。
默认的,当我们关闭浏览器的时候,cookie会被删除。
但可以通过修改cookie 的expire time使cookie在一定时间内有效。
3:Oauth(第三方登录)
这是一个第三方的。
也不是有多适用。一般产品推广的时候,为了更多的获取流量获取用户,就用这种方式,
直接或间接的使用qq或者微信的这个用户群。就可以很快的为新产品拉来很多用户。
这个也是一种认证机制,但是他借助于第三方平台。
官方文档:
OAuth(开放授权)是一个开放的授权标准,
允许用户让第三方应用访问该用户在某一web服务上存储的私密的资源(如照片,视频,联系人列表),
而无需将用户名和密码提供给第三方应用。
OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。
每一个令牌授权一个特定的第三方系统(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。
这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。
这种基于OAuth的认证机制适用于个人消费者类的互联网产品,
如社交类APP等应用,但是不太适合拥有认证权限管理的企业应用。
4:Token Auth(令牌)
它的逻辑是:这个token令牌就相当于古代的尚方宝剑,不管谁拥有了它,哪怕你长的特别搓,我也认为你牛逼。
因为见尚方宝剑,如同面见皇上,牛逼到不行,至高无上的权利。
简单理解:只要用户一登录,服务器端就生成一个令牌。
但是此时我服务器端不会保存这个令牌,将令牌返回给你,你自己想办法保存。
用户想访问我的接口,拿上你的令牌就行了。
那有的人就问了,你服务端不存,那我怎么知道这个令牌对不对呢?(令牌也有可能伪造啊)
其实我们服务器端有一个算法,生成令牌的时候,就是靠这个算法来生成的。
所以在验证的时候,服务器端也用这个算法来验证。
那又有人问了,你用这个算法来验证和我之前用session验证有区别吗?
其实区别就在于服务器端用算法来验证还是运行在Java虚拟机内部,并没有跨平台,而且速度快。
但是在session中取的话,就算存在redis中也算是跨平台了,也需要耗费额外的资源。
所以说,验证token的真假,就是用一个简单的算法,验证一下就行了。
注意:
token的生成里面,也需要加一个唯一的标识,一般就是公司的一个唯一标识,或者项目的标识,这个自己界定。
官方文档:
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。
大概的流程是这样的:
1. 客户端使用用户名跟密码请求登录
2. 服务端收到请求,去验证用户名与密码
3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里
5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据。
最后在整理下token机制和cookie机制的优缺点?
1:token支持跨域访问
cookie是不支持跨域的,所以说token在分布式项目中有很好的作用。
2:无状态
Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,
只需要在客户端的cookie或本地介质存储状态信息.
服务器端没有存登录信息的这样一个压力,
你存一两人好说啊,那我要存上亿个人,redis服务器就受不了了。
3:更适用于移动应用:
当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,
Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
4:CSRF:
因为不再依赖于Cookie,所以就不需要考虑对CSRF(跨站请求伪造)的防范。
因为CSRF攻击就是利用cookie,具体怎么弄的,我也不是很清楚。
5:性能:
一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算的Token验证和解析要费时得多。
其实这个性能也很好理解:
之前从session中取信息,跟现在用一个算法去验证,那算法肯定要快啊。
6:标准化
一般API可以采用标准化的JSON Web Token (JWT)来实现,
这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)
下次我在分享下自己项目中使用JWT验证的一个例子。