blog/docs/dev/backend/iam.md
王一之 388012cf93
All checks were successful
Release / deploy (push) Successful in 5m48s
IAM?认证?授权?傻傻分不清楚
2024-04-01 17:49:12 +08:00

157 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# IAM认证授权傻傻分不清楚
经常会听说一些和鉴权相关的名词像什么JWT、SSO、OAuth2、RBAC、IAM什么什么的
虽然每一个都知道它们是什么,但是它们之间的关系和区别就不是那么清楚了。
有时候知识体系比较零散,不知道从哪里开始学习,所以就写了这一篇文章,把这些名词串起来,帮助自己理清思路。
其中有些我认为比较复杂或者容易混淆的概念,我会着重说明一下。
本文主要围绕IAM、认证、鉴权这些概念进行讲解介绍它们相关的实现方式与名词。如果有什么错误与不足欢迎指正。
## 身份和访问管理IAM
> [什么是IAM](https://www.cloudflare.com/zh-cn/learning/access-management/what-is-identity-and-access-management/),这里有一篇文章,我觉得是不错的。
身份和访问管理IAM是一种安全性的框架用于确保适当的人员能够访问适当的资源同时防止未经授权的人员访问敏感资源。像阿里云RAM、腾讯云CAM、AWS等云服务商都提供了IAM服务可能你也经常使用只是他们的名字不一同而已。
IAM主要包含两大块认证和授权这两个概念是不同的但是又是相辅相成的。
### 认证Authentication
认证经常简写为Authn是指确认用户的身份确保用户是其声称的那个人。
### 授权Authorization
授权经常简写为Authz是指确定用户是否有权限访问某个资源。
## 登录和认证
登录应该算是认证流程的一部分。
登录是用户行为,是用户开始认证流程的动作。在这个阶段,用户通过提供身份信息(如用户名和密码)来请求访问系统。
认证是系统对用户提供的身份信息进行验证的过程。认证的目的是确保用户是其声称的那个人。如果认证成功,表明系统已经确认了用户的身份。
一般来说,认证成功后会颁发一个令牌给用户,用户可以通过这个令牌来访问系统的资源,这块应该是属于会话管理的范畴。
### 登录
按照上面的定义来说,下面这些场景都可以称为登录,都是用户提供身份信息的过程,
这里也只是列举了一些常见的登录方式:
#### 用户名密码/扫码/指纹/人脸登录
这些都是用户提供自己的身份信息,系统验证后确认用户身份的方式。
##### 多因素认证MFA
多因素认证是指在用户登录时,除了提供用户名和密码外,还需要提供其他因素来确认用户身份。
常见的多因素认证有手机验证码、邮箱验证码、指纹、人脸、动态密码OTP
总的来说,就是提供多种身份信息来确认用户身份,可以和其它登录方式组合使用。
#### OAuth2/OIDC三方应用登录
OAuth2 是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用。
OIDC 是在 OAuth2 的基础上,增加了用户信息的获取。
例如,用户可以通过 GitHub 账号登录某个网站,这个网站会跳转到 GitHub 的登录页面用户输入用户名和密码后GitHub 会返回一个令牌给这个网站,这个网站就可以通过这个令牌获取用户的信息。
#### SSO单点登录
SSO 是一种让用户只需要登录一次就可以访问多个应用的技术。
用户登录后,系统会颁发一个令牌,用户在访问其他应用时,只需要携带这个令牌即可。
例如,淘宝和天猫,在登录淘宝后,用户可以直接访问天猫,而不需要再次登录。甚至其它阿里系的应用也可以直接登录。
SSO更多时候是同一个公司内部的应用之间的登录而OAuth2更多是不同公司之间的应用登录。
而且SSO更多是一种思想具体实现方式有很多种比如CAS、JWT等OAuth2也可以实现SSO。
### 会话管理
当认证成功之后,我们需要颁发一个令牌给用户,用这个令牌来维护用户的会话。否则用户每次请求都需要重新认证。
会话我们可以使用 Cookie、Session、Token 等来实现,常见的有:
#### Cookie
Cookie 是服务器发送给浏览器的一小段数据,浏览器会保存在本地,每次请求都会带上这个数据。
我们可以在 Cookie 中存储用户的身份信息严格来说我认为Cookie只是一个载体你可以把令牌放在Cookie里也可以放在其他地方只要能够保证用户的会话即可通常结合其它技术一起使用。
#### Session
Session 是服务器端保存用户信息的一种机制用户登录后服务器可以生成一个Session把用户的信息保存在这个Session中然后把这个Session的ID返回给用户用户每次请求都带上这个Session ID。
Session 可以保存在数据库中,当然也可以保存在 Redis 等缓存中。通常Session都是以 Cookie 的形式返回给用户。
我认为只要是只返回一个ID而不是用户的身份信息用户的身份信息都保存在服务器端都可以称为Session哪怕你叫这个ID为Token也好。
#### JWT
JWTJSON Web Token是一种开放标准RFC 7519用于安全地在两方之间传输信息主要包含`header.payload.signature`三部分,使用`.`进行分割。这种方式也不止JWT应该对应了所有的无状态Token模式。
其中数据都是以明文形式存在,不加密,使用签名来保证数据的完整性和防篡改,所以不要在 JWT 中存储敏感信息。
JWT本身是无状态的也就是说服务器不需要保存用户的会话信息只需要验证JWT的签名即可。
也因为这个特性JWT无法主动失效只能等待过期时间到了之后才会失效密钥也是不能泄漏否则可以随意伪造。
我觉得JWT是不适合来做会话管理的在有主动失效之类的需求时又不得不依赖数据库等其它方式来实现倒是变成了像Session一样的东西。
不过也看实际情况另外JWT也广泛用于SSO、分布式系统、API认证等场景。
#### 双Token
这其实和上面的没啥关系,只是我觉得可以放在这里说一下。
双token是指用户在登录后服务器会返回两个Token给用户一个有效时间较短例如2小时的访问token`access_token`一个有效时间长例如30天的刷新token`refresh_token`
每次请求时只发送`access_token``refresh_token`只保存在客户端例如localStorage`access_token`过期时,客户端会发送`refresh_token`给服务器,服务器会返回一个新的`access_token`给客户端并失效老的。
这样做主要是为了保障安全性和用户体验,`access_token`有效时间短,尽量减少泄漏风险,而`refresh_token`有效时间长用户不会频繁使用。用户体验上用户10多天都没有操作也不用重新登录。
感觉APP常用这种方式网页的会少一些。
## 鉴权
鉴权主要是确定用户是否有权限访问某个资源,是在认证成功后的一个环节。
如果A部门可以访问B部门的私有资源那么岂不乱套了。
鉴权的实现方式有很多种常见的有ACL访问控制列表、RBAC基于角色的访问控制、ABAC基于属性的访问控制等。
简单的IAM系统可能只需要一个ACL就够了复杂的更多是用RBAC和ABAC。
像公司的OA系统一般都是RBAC各大云服务商的IAM一般都是ABAC
像阿里云RAM、腾讯云CAM都抽象出来了用户、用户组、策略、角色等概念虽然是ABAC但是看起来很像RBAC使用起来也更方便。
像ABAC一般都是使用像下面的策略语言来描述
```json
{
"version": "2.0",
"statement": [
{
"action": [
"dnspod:CreateRecord",
"dnspod:DescribeDomain",
"dnspod:CreateDomain",
"dnspod:DescribeRecordList",
"dnspod:DeleteRecord",
"dnspod:ModifyRecordStatus"
],
"effect": "allow",
"resource": "*"
}
]
}
```
ABAC可以更灵活的控制权限但是也更复杂像上面的如果我希望某个用户只能控制某一个域名那么我可以在`resource`中指定而RBAC就不太好实现了。
## 最后
如果你想设计一个IAM系统希望本篇文章能够对你有所帮助。若有什么错误或者不足欢迎指正。