常见的登录方式有以下几种:
Cookie + Session 登录
Token 登录
SSO 单点登录
OAuth 第三方登录
1. Cookie + Session 登录
Cookie:
HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。
为了解决这个问题,Cookie出现了,Cookie 是由客户端保存的小型文本文件,其内容为一系列的键值对。Cookie 是由 HTTP 服务器设置的,保存在浏览器中。Cookie会随着 HTTP请求一起发送。
Session:
有了Cookie,服务端就可以知道是哪个用户传来的信息了,如果要对信息进行验证,还需要通过Session。客户端在请求服务端时,服务端会为这次请求开辟一次内存空间,这就是Session对象,这样就可以进行登录验证了。
Session 存储在服务器端的,避免在客户端 Cookie 中存储敏感数据。Session 可以存储在 HTTP 服务器的内存中,也可以存在内存数据库(如redis)中。
认证机制:
Cookie/Session认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象;通过客户端带上来Cookie对象来与服务器端的session对象匹配来实现状态管理的。默认的,当我们关闭浏览器的时候,cookie会被删除。但可以通过修改cookie 的expire time使cookie在一定时间内有效。
①首次登录
用户在登录时,输入账号密码发送HTTP请求,服务器验证账号密码之后,服务端会创建SessionId,并将它保存起来。服务端响应这个HTTP请求,并通过Set-Cookie头信息,将SessionId写入到Cookie中。 ②之后登录
用户再次发送请求的时候,会自动带上第一次登录写入的Cookie,服务端会将Cookie中的SessionId和保存在服务端的SessionId进行对比,如果一致,身份验证就成功了,否则就验证失败。
缺点:
维护成本高: 如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。
服务器压力增大:通常session是存储在内存中的,每个用户通过认证之后都会将session数据保存在服务器的内存中,而当用户量增大时,服务器的压力增大。
CSRF跨站伪造请求攻击:session是基于cookie进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。可以添加csrf_token处理。
扩展性不强:如果将来搭建了多个服务器,虽然每个服务器都执行的是同样的业务逻辑,但是session数据是保存在内存中的(不是共享的),用户第一次访问的是服务器1,当用户再次请求时可能访问的是另外一台服务器2,服务器2获取不到session信息,就判定用户没有登陆过。
手机请求不支持:Cookie不支持手机端访问的
2. Token 登录
Token 是服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。
登录时,客户端通过用户名与密码请求登录
服务端收到请求去验证用户名与密码
验证通过,服务端会签发一个带签名的Token,再把这个Token以响应发给客户端
客户端收到Token,存储到本地,如Cookie、SessionStorage、LocalStorage
客户端每次像服务器请求API接口时候,都要带上Token
服务端收到请求,验证Token,如果通过就返回数据,否则提示报错信息
①首次登录
用的在登录时,输入账号密码,服务器会验证账号密码,验证无误后会创建Token,然后将Token返回给客户端,客户端将其保存下来。 ②再次登录
用户再次发起请求时,需要带上之前保存在本地内存的Token,服务器端验证成功之后,则身份验证成功,响应客户端的请求。
特点:
无状态、可扩展:在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。
安全性:请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,少了对session操作。
时效: Token 下发之后,只要在生效时间之内,就一直有效,如果服务器端想收回此 Token 的权限,并不容易。如果失效,就会重新进行登录验证,服务器端会返回状态码401
需要注意的是,前端每次路由跳转时,需要判断本地内存中有无 token ,没有则跳转到登录页。有则请求获取用户信息,改变登录状态。
3. SSO 单点登录
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
SSO一般都需要一个独立的认证中心(passport),子系统的登录均得通过passport,子系统本身将不参与登录操作,当一个系统成功登录以后,passport将会颁发一个令牌给各个子系统,子系统可以拿着令牌会获取各自的受保护资源,为了减少频繁认证,各个子系统在被passport授权以后,会建立一个局部会话,在一定时间内可以无需再次向passport发起认证。
①首次登录
首先用户访问网站 a.com 下的 pageA 页面。由于没有登录,则会重定向到认证中心,并带上回调地址 www.sso.com?return_uri=a.com/pageA,以便登录后直接进入对应页面。
用户在认证中心输入账号密码,提交登录。
认证中心验证账号密码有效,然后重定向 a.com?ticket=123 带上授权码 ticket,并将认证中心 sso.com 的登录态写入 Cookie。
在 a.com 服务器中,拿着 ticket 向认证中心确认,授权码 ticket 真实有效。
②认证中心登录之后,再次访问a.com下页面
这个时候,由于 a.com 存在已登录的 Cookie 信息,所以服务器端直接认证成功。 ③认证中心登录之后,访问b.com下页面
这时由于认证中心存在之前登录过的 Cookie,所以也不用再次输入账号密码,直接返回第 3 步,下发 ticket 给 b.com 即可。
退出流程
这样我们已经完成了单点登录,在同一套认证中心的管理下,多个产品可以共享登录态。那么问题来了:在一个产品中退出了登录,怎么让其他的产品也都退出登录?
我们可以看看上面的第四步,每一个产品在向认证中心验证 ticket 时,其实可以顺带将自己的退出登录 api 发送到认证中心。
当某个产品 c.com 退出登录时:
清空 c.com 中的登录态 Cookie。
请求认证中心 sso.com 中的退出 api。
认证中心遍历下发过 ticket 的所有产品,并调用对应的退出 api,完成退出。
(1)优点:
简化管理
提高用户的效率
提高开发人员的效率
用户不再被多次登录困扰,也不需要记住多个 ID 和 密码。
SSO 为开发人员提供了一个通用的身份验证框架。 实际上,如果 SSO 机制是独立的,那么开发人员就完全不需要为身份验证操心。
如果应用程序加入了单点登录协议,管理用户帐号的负担就会减轻。简化的程度取决于应用程序,因为 SSO 只处理身份验证。所以,应用程序可能仍然需要设置用户的属性(比如访问特权)。
(2)缺点:
CPU开销较大:在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。
安全隐患 :因为只需要登录一次,所有的授权的应用系统都可以访问,可能导致一些很重要的信息泄露。
不利于重构 : 因为涉及到的系统很多,要重构必须要兼容所有的系统,可能很耗时
4. OAuth 第三方登录
单点登录完成了多产品的登录态共享,但都是建立在一套统一的认证中心下,过程有些复杂。实际上很多大厂为我们提供了第三方的登录服务,可以直接通过第三方的账号登录自己的应用。
所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。
OAuth 是 Open Authorization 的简写,它为用户资源的授权提供了一个安全又简易的标准。与以往的授权方式不同之处是 OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 OAuth是安全的。
OAuth 本身不存在一个标准的实现,后端开发者自己根据实际的需求和标准的规定实现。其步骤一般如下:
第三方要求用户给予授权
用户同意授权
根据上一步获得的授权,第三方向认证服务器请求令牌(token)
认证服务器对授权进行认证,确认无误后发放令牌
第三方使用令牌向资源服务器请求资源
资源服务器使用令牌向认证服务器确认令牌的正确性,确认无误后提供资源
5. 使用场景
Cookie + Session :适合于简单的后端架构,需开发人员自己处理好安全问题。
Token :方案对后端压力小,适合大型分布式的后端架构,但已分发出去的 token ,如果想收回权限,就不是很方便了。
SSO :单点登录,适用于中大型企业,想要统一内部所有产品的登录方式。
OAuth 第三方登录:简单易用,对用户和开发者都友好,但第三方平台很多,需要选择合适自己的第三方登录平台。