身份授权——OAuth 2.0协议

OAuth 2.0

Oauth 2.0

Oauth 2.0是Oauth的最新版本,是目前主流的授权机制。那么它在哪里使用呢?答案就是第三方的授权登录。主流的互联网网站除了支持用户名+密码和手机号+验证码登录之外,一般还会有微信、QQ、Github登录等,国外常见的有Facebook、Twitter、Instagram、google,一些公司接入一些第三方服务商的系统的时候,还会要求通过企业邮箱进行授权登录,这些都是通过Oauth 2.0进行授权,OIDC进行认证,来实现第三方登录的。

授权第三方应用进入系统后,它会产生一个短期的进入令牌(Access Token),用来代替密码,供第三方应用使用。

为什么需要 Oauth 2.0

假设都是通过账号+密码登录网站,当你在一个网站A要使用一个云盘中的信息,那么用账号+密码在网站A登录,你的凭据就会被网站A知道,那么你的云盘数据就可能泄露。这个时候提出一种不需要输入账号密码又能获取在云盘中的资源,为了解决确认身份的问题,就产生了通过Oauth 授权,给一个短期的凭据,既不会让你的凭据泄露也可以让你暂时登录获取相关资源,凭据过期后就没法获取你的相关资源

Oauth 2.0 Structure

有四个主要的角色:

  • 资源拥有者(Resource Owner):终端用户,拥有受保护资源(如用户数据、照片等)的所有权,通过授权同意客户端访问其资源(例如用微信登录第三方App时点击"允许")。
  • 客户端(Client):代表用户访问资源的第三方应用(如网站A/B/C/D或移动App)。必须先在授权服务器注册,获取client_id等凭证。分为机密客户端(能安全存储密钥,如后端服务)和公开客户端(无法保密密钥,如前端应用)。
  • 授权服务器(Authorization Owner):验证用户身份(如跳转登录页面)。管理用户授权流程(如询问用户是否同意授权)。颁发访问令牌(Access Token)和刷新令牌(Refresh Token)。
  • 资源服务器(Resource Server):存储并保护用户资源(如微信存储用户个人信息、GitHub存储代码)。通过验证客户端提供的Access Token决定是否返回资源。通常与授权服务器分离,但可同属一个系统(如微信的授权和资源API在同一平台)。

Oauth 2.0 的四种授权类型

Oauth 2.0 规定了四种授权类型:

  • 授权码(authorization-code)
  • 隐藏式(implicit)
  • 密码式(password):
  • 客户端凭证(client credentials)

1. 授权码

在这里插入图片描述

第三方应用先申请一个授权码,在用该码获取令牌

  • 第一步,用户跳转授权
    • 前端生成授权链接,用户点击后跳转至授权服务器(如Google/OAuth服务商)
    • https://b.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read(例)
    • 用户登录并同意授权后,授权服务器返回授权码到redirect_url
    • https://a.com/callback?code=AUTHORIZATION_CODE(例)
  • 第二步,后端用授权码换取令牌
    • 用code+client_secret向授权服务器请求access_token
    • https://b.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL(例)
    • 授权服务器返回access_token和refresh_token
example
{    
 "access_token":"ACCESS_TOKEN",
 "token_type":"bearer",
 "expires_in":2592000,
 "refresh_token":"REFRESH_TOKEN",
 "scope":"read",
 "uid":100101,
 "info":{...}
}
  • 第三步,API调用
    • 后端存储access_token,并在访问资源服务器时带上
PS:
  • 授权码仅一次性有效,防止中间人攻击。
  • client_secret 仅后端可见,避免泄露。
  • refresh_token 可换取新 access_token,避免用户频繁授权。

2. 隐藏式

在这里插入图片描述

允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)“隐藏式”(implicit)

  • 第一步,前端直接请求令牌

    • 前端跳转至授权服务器,response_type=token:
      https://auth-server.com/authorize? response_type=token& client_id=YOUR_CLIENT_ID& redirect_uri=https://your-app.com/callback& scope=read_profile
    • 用户授权后,授权服务器直接返回 access_token 到 redirect_uri 的 URL 锚点(#):

https://yourapp.com/callback#access_token=TOKEN&expires_in=3600

  • 前端JS解析 access_token(锚点不会发送到服务器,减少泄露风险)。

  • API 调用

    • 前端直接使用 access_token 访问 API:
      fetch("https://api.resource-server.com/data", { headers: { "Authorization": "Bearer ACCESS_TOKEN" } });
PS:
  • 令牌直接暴露给前端,可能被恶意JS窃取。
  • 必须设置短有效期(如1小时),避免长期风险。
  • 仅适用于低敏感度场景(如天气API)。

3. 密码式

在这里插入图片描述

  • 用户直接输入账号密码

    • 前端收集用户密码,直接发送给后端(不能存储!)。

    • 后端向授权服务器请求令牌:

    • 授权服务器返回 access_token。


POST https://auth-server.com/token
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=YOUR_CLIENT_ID

PS:
  • 用户需明文提供密码,仅限受信任应用(如公司内部工具)。
  • 必须使用HTTPS,防止中间人窃取密码。
  • 不推荐公开应用使用,风险极高!

4. 客户端凭证

在这里插入图片描述

  • 应用直接用 client_id 和 client_secret 获取令牌

POST https://auth-server.com/token
  grant_type=client_credentials&
  client_id=YOUR_CLIENT_ID&
  client_secret=YOUR_CLIENT_SECRET
  • 授权服务器返回 access_token(仅用于该应用,不关联用户)。
PS:
  • 无用户参与,仅限服务端使用(如定时任务、微服务通信)。
  • 不能用于用户数据访问,仅限应用级权限。

Oauth 2.0 Flow

在这里插入图片描述

流程:

  1. 用户在客户端(如网站A)点击“用微信登录”。

  2. 客户端将用户重定向到授权服务器的授权端点(如微信的OAuth页面),并携带以下参数:

    • client_id: 客户端注册时获得的ID。

    • redirect_uri: 授权成功后回调的URI。

    • scope: 请求的权限范围(如读取用户信息)。

    • state: 随机字符串,防止CSRF攻击。

  3. 用户在授权服务器登录(如输入微信账号密码),并确认是否同意客户端请求的权限。

  4. 授权服务器将用户重定向回客户端的redirect_uri,并在URL中携带一个短期有效的code(授权码)和state。

  5. 客户端后端(非前端!)向授权服务器的令牌端点发送请求,包含:

    • code: 上一步获取的授权码。

    • client_secret: 客户端的密钥(确保请求来自合法客户端)。

  6. 授权服务器验证通过后,返回access_token(和可选的refresh_token)。

  7. 客户端用access_token调用资源服务器API(如获取用户个人信息)。

  8. 资源服务器验证Token有效性后返回请求的数据。

  9. 客户端显示用户信息或完成登录。

Oauth 2.0 和 OIDC 的关系

  • OAuth 2.0:仅授权,不提供用户身份认证。

  • OIDC:基于OAuth 2.0的扩展,添加id_token(JWT格式)明确用户身份信息。

    • sub(用户ID)、iss(签发者)、aud(受众)、exp(过期时间)。

常见攻击与防御

攻击类型防御措施技术实现说明
CSRF使用state参数并验证回调来源1. 生成随机state存入Session
2. 回调时校验state是否匹配
令牌泄露短期令牌 + HTTPS + 范围限制1. 设置expires_in≤3600
2. HSTS强制HTTPS
3. 按需申请scope=read
授权码拦截PKCE + 单次授权码1. 客户端生成code_verifiercode_challenge
2. 服务端验证哈希一致性
密码爆破限流 + MFA1. 令牌桶算法限流
2. 集成Google Authenticator/SMS验证

参考资料

Oauth 2.0 / OIDC / PKCE / JWT 全面介绍

阮一峰的网络日志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值