登录鉴权
登录方式
- 用户名+密码登录。最原始的登录方式,实现简单。用户在注册时提供一个不重复的唯一标识,作为用户的区分,如用户可以取一个与其他用户不重复的用户名,或者提供邮箱地址、手机号码等身份标识。同时,用户指定密码,用于用户的登录。后端生成账户,使用 hash 值保存密码。
- 验证码登录。登录时,由服务端向用户的第三方联系方式发送验证码,用户使用第三方联系方式并查收验证码,用户输入验证码进行登录。
- 双因素验证登录。同时使用密码登录和验证码登录,两种方式都通过了,才能登录。为了提高登录操作的安全性,防止密码泄露。
登录状态保持
由于 http 协议的无状态性,每次 http 请求均需要进行验证,为了减少验证的次数,提高用户的体验,需要未登录的用户颁发授权令牌,利用浏览器的 cookie 机制,cookie 可以在每次请求时携带一部分信息,由 cookie 携带用户令牌,免去用户在登录授权之后打重复的登录操作。具体实现的时候,可以分成 session 实现和 jwt 实现。
- session。用户登录之后,对用户发放 sessionID,在服务器端记录了 sessionID 的登录情况,在之后的请求中,校验 cookies 中的 sessionID 是否合法登录,从而来判断是否放行请求。该方法对服务器的存储压力较大,并且如果进行分布式架构的话需要使用 redis 等存储 sessionID,从而实现在服务器集群中共享登录状态。
- jwt。用户登录之后,对用户发放 jwt 令牌。令牌由三部分 base64 的编码的信息构成,使用
.进行分隔,<header>.<payload>.<sign>。其中 header 记录了 jwt 的一些元信息,payload 代表了被签名的信息内容,sign 代表签名,签名是对 header 和 payload 的签名,使用一定的算法和秘钥进行签名,秘钥是服务端的机密文件。用户后续请求时,服务端检查令牌,没有令牌则拒绝,如果有令牌则校验令牌,使用同样的算法和秘钥对 header 和 payload 的内容进行签名计算,比对用户提供的令牌中的 sign 和现场计算的 sign 是否相同,如果相同则放行,不同则拒绝。该方式,使用了时间换空间的思路,将用户的登录状态存储在用户的机器上,减轻了服务端的存储压力,并且使得服务端无需管理登录状态。
单点登录架构
在大型的服务项目中,将一组用户账户信息共同的服务的登录服务托管到同一个服务器上,从而实现一个账户、多端登录,优化用户体验,同时将服务端的任务进行明确分工。在用户登录时访问统一的登录服务器,由登录服务器统一发放 token,并且在后续的校验中,可以采用不同的方式进行实现,例如,在使用 nginx 对需要权限控制的请求代理到 gateway 集群,gateway 集群对令牌进行校验,然后将请求传递到相应的上游服务,或者拒绝服务。
三方登录
在构建服务时,使用一些现有的第三发机构提供的服务,代理用户在第三方服务上进行操作。这是一个获取授权的过程,第三方授权我们代替用户对其在第三方上的资源进行管理和操作。具体的操作需要查看第三方服务提供商的开发者文档。经常使用的三方登录技术为 OAuth2。它有四种主要的授权方式(授权码、简化模式、密码模式、客户端凭据模式),其中最常用于第三方登录的是授权码模式(Authorization Code Grant)。
授权码模式
- 用户点击第三方登录按钮。例如,用户在我们的应用上点击“用 Google 登录”等按钮。
- 请求授权码。用户被重定向到第三方提供者的授权页面(如 Google 的登录页面)。用户登录并同意授权我的应用访问其信息。
- 获取授权码。第三方提供者将用户重定向回我的应用,并带上一个授权码。
- 交换授权码为访问令牌。我的应用用授权码向第三方提供者的授权服务器请求访问令牌,最后获得访问令牌。
- 使用访问令牌访问资源。我的应用使用访问令牌从第三方提供者的 API 获取用户信息。
简化模式
- 用户通过我的客户端向授权服务器请求令牌。
- 用户被重定向到授权服务器进行身份验证。
- 如果验证通过,授权服务器直接返回访问令牌。
密码模式
- 用户告诉我们用户在第三方服务的用户名和密码。
- 我们用这些凭据向授权服务器请求访问令牌。
- 授权服务器验证凭据并返回访问令牌。
客户端凭据模式
- 客户端用自身的客户端 ID 和密钥向授权服务器请求访问令牌。
- 授权服务器验证凭据并返回访问令牌。