OAuth2 概念

📅 发布时间:2026/7/15 10:52:04 👁️ 浏览次数:
OAuth2 概念
前言你是否有过这样的经历在某个网站或 App 上看到微信登录、Google 登录或GitHub 登录的按钮点击一下扫码确认就成功登录了整个过程快捷方便而且你不需要记住新密码。但你有没有想过为什么用微信登录其他网站时不需要把微信密码告诉那个网站那个网站是怎么知道你是谁的这背后到底发生了什么答案就是OAuth2——一个让第三方应用获得有限访问授权的开放标准协议。今天我们就来彻底搞懂 OAuth2 的工作原理。一、OAuth2 是什么OAuth2Open Authorization 2.0是一个授权协议它的核心思想是让用户授权第三方应用访问其在某个服务上的资源而无需将用户名和密码提供给第三方应用。核心概念想象这样一个场景你想用某个应用管理你的照片这个应用需要访问你的 Google 相册但你不想把 Google 密码告诉这个应用OAuth2 就是为了解决这个问题而诞生的四种角色在 OAuth2 协议中有四个重要的角色资源拥有者就是用户拥有资源的所有权客户端第三方应用想要访问用户的资源授权服务器负责验证用户身份并颁发访问令牌资源服务器托管受保护资源的服务器二、真实的第三方登录流程让我们以用微信登录某网站为例看看完整的过程是怎样的。第一步点击微信登录按钮你在网站上看到这个按钮 ┌─────────────────┐ │ 微信登录 │ └─────────────────┘点击后网站内部会构建一个 URL 并跳转到微信const authUrl https://open.weixin.qq.com/connect/qrconnect? appidwx1234567890 redirect_urihttps%3A%2F%2Fwww.example.com%2Fcallback response_typecode scopesnsapi_login stateabc123#wechat_redirect window.location.href authUrl你的浏览器地址栏变成了微信的授权页面。第二步微信显示授权页面此时你看到的是┌─────────────────────────────┐ │ 微信授权登录 │ │ │ │ [二维码] │ │ 请使用微信扫码 │ │ │ │ 登录后该网站将获得 │ │ ☑ 您的公开信息昵称等 │ │ │ │ [取消] [确认] │ └─────────────────────────────┘第三步扫码并确认授权你用微信扫码点击确认。微信服务器会验证你的身份生成一个临时的授权码重定向回原网站并带上这个授权码浏览器地址栏变成https://www.example.com/callback?codeAUTH_CODE_XYZ123stateabc123第四步网站后台换取用户信息这是最关键的一步网站的后台拿到授权码后会用它向微信服务器换取用户信息const response await fetch(https://api.weixin.qq.com/sns/oauth2/access_token, { method: POST, body: JSON.stringify({ appid: wx1234567890, secret: SECRET_abc123, // 网站的密钥 code: authCode, grant_type: authorization_code }) }) const data await response.json() // 微信返回 // { // access_token: ACCESS_TOKEN_xxx, // openid: o1234567890, // expires_in: 7200 // }然后网站用这个 access_token 获取用户详细信息并在自己的数据库中创建或更新用户最后给你一个自己网站的登录凭证。第五步登录成功你被重定向到网站的首页已经成功登录了。三、为什么 OAuth2 更安全传统方式危险你 → 把微信密码输入到网站 ↓ 网站拿到你的密码 ↓ 网站可以用你的密码登录微信 ↓ 如果网站是假的密码就被盗了OAuth2 方式安全你 → 只在微信输入密码 ↓ 微信验证通过 ↓ 微信告诉网站这个人是我认证过的 ↓ 网站只知道这是某个微信用户 ↓ ✅ 网站永远拿不到你的密码关键安全保障密码隔离你的密码只存储在微信服务器第三方网站永远不会知道有限授权你只授予网站必要的权限如昵称、头像而不是全部信息临时凭证授权码只能用一次有效期很短通常 10 分钟可撤销你可以在微信设置中随时撤销对某个网站的授权四、OAuth2 的四种授权模式除了我们刚才看到的授权码模式最安全、最常用OAuth2 还提供了其他三种模式1. 授权码模式最安全最常用适用于有服务器的 Web 应用用户看不到 access_token2. 简化模式直接在前端获取 token适用于纯前端应用如 SPA安全性较低3. 密码模式用户直接提供用户名和密码不推荐使用仅适用于官方应用4. 客户端模式机器对机器的授权不涉及用户适用于后台服务调用五、Token 的奥秘在 OAuth2 中有两种重要的令牌Access Token访问令牌用于访问受保护资源有效期短通常 1-2 小时每次调用 API 时都需要携带Refresh Token刷新令牌用于获取新的 access_token有效期长数天到数月只能使用一次Token 刷新流程当 access_token 过期时网站可以用 refresh_token 获取新的 token而不需要用户重新授权POST /token { grant_type: refresh_token, refresh_token: tGzv3JOkF0XG5Qx2TlKWIA } // 响应 { access_token: 新的access_token, refresh_token: 新的refresh_token, expires_in: 3600 }六、安全最佳实践1. PKCE 扩展防止授权码被拦截拦截攻击在移动应用和 SPA 中特别重要生成一个随机的 code_verifier用 code_verifier 生成 code_challenge授权时发送 code_challenge换取 token 时验证 code_verifier2. State 参数防止 CSRF 攻击生成随机字符串作为 state授权请求时带上 state回调时验证 state 是否一致3. Token 存储不要将 access_token 存储在 localStorage易受 XSS 攻击推荐使用 httpOnly Cookie 或内存存储七、前端实现示例class OAuth2Client { constructor(config) { this.clientId config.clientId this.redirectUri config.redirectUri this.authUrl config.authUrl this.tokenUrl config.tokenUrl } getAuthorizationUrl() { const params new URLSearchParams({ response_type: code, client_id: this.clientId, redirect_uri: this.redirectUri, scope: read:user, state: this.generateState() }) return ${this.authUrl}/authorize?${params} } async exchangeCodeForToken(code) { const response await fetch(this.tokenUrl, { method: POST, headers: { Content-Type: application/x-www-form-urlencoded, }, body: new URLSearchParams({ grant_type: authorization_code, code: code, client_id: this.clientId, redirect_uri: this.redirectUri }) }) return response.json() } generateState() { return Math.random().toString(36).substring(2) } }八、常见应用场景1. 社交登录使用微信、Google、GitHub 账号登录其他网站2. 第三方应用授权应用访问你的 Google 相册、微信朋友圈等3. API 授权允许第三方服务调用平台的 API4. 企业单点登录企业内部系统统一登录九、总结OAuth2 是一个强大而灵活的授权协议它让第三方应用可以在不暴露用户密码的情况下获得有限的访问权限。核心要点用户密码永远不会泄露给第三方授权是有限的、可撤销的使用临时凭证授权码和短期 token 提高安全性授权码模式是最安全的实现方式下次当你使用微信登录时你就知道背后发生了什么这种设计既方便又安全这就是为什么越来越多的网站支持第三方登录的原因。