:OAuth2 到底解决了什么问题?一篇讲透授权与第三方登录)
上一篇我们讲了《企业认证与安全体系六Gateway 为什么能统一鉴权一篇讲透微服务认证体系》到这里我们已经把企业内部认证链路基本串起来了客户端 ↓ Gateway ↓ JWT 校验 ↓ Redis 会话检查 ↓ 业务服务这套体系主要解决的是用户如何登录我们自己的系统以及系统内部如何完成统一鉴权。但是真实企业项目里还会遇到另一类场景使用微信登录 使用 QQ 登录 使用 GitHub 登录 使用企业微信登录 使用钉钉登录 使用 Google 登录这时候问题来了如果用户要使用微信登录我们的系统我们总不能让用户把微信账号密码直接输入到我们的系统里吧这显然不安全。于是OAuth2 出现了。今天我们就从工程视角讲清楚OAuth2 到底解决了什么问题一、先说结论OAuth2 解决的核心问题不是单纯的“登录”而是授权。更准确地说OAuth2 解决的是第三方应用在不获取用户账号密码的情况下经过用户授权后访问用户资源的问题。举个例子。你开发了一个网站支持微信登录。用户点击微信登录后你的网站想要拿到用户的微信头像、昵称、openid。但是这些数据在微信服务器上。你的系统不能直接访问。用户也不可能把微信账号密码告诉你。所以需要一个安全机制用户同意 ↓ 微信授权 ↓ 你的系统拿到授权结果 ↓ 你的系统获取用户基础信息这就是 OAuth2 要解决的问题。二、为什么不能直接要用户账号密码假设没有 OAuth2。你的网站想支持微信登录最简单粗暴的方式是请输入微信账号 请输入微信密码然后你的系统拿着用户账号密码去微信服务器登录。这有什么问题问题非常大。1. 用户不敢给微信账号密码是用户的核心资产。用户凭什么相信你的系统如果用户把微信账号密码交给你的系统本质上就是把自己的完整账号控制权交给了你。这显然不合理。2. 第三方系统不应该保存用户密码如果你的数据库泄露了用户微信账号密码就全泄露了。这不是普通 Bug而是严重安全事故。所以一个正常的第三方系统不应该直接接触用户在其他平台的账号密码。3. 无法控制权限范围你的系统可能只是想拿用户头像和昵称。但是一旦拿到了账号密码就等于拥有了用户完整权限。这明显违背了最小权限原则。正确的做法应该是你需要什么权限 用户就授权什么权限而不是一上来就拿用户全部账号权限。4. 用户无法随时取消授权如果用户不想让你的系统继续访问微信信息应该可以随时取消授权。但如果你拿的是账号密码就很难做到细粒度控制。所以第三方登录绝不能让用户把账号密码交给第三方应用。OAuth2 的价值就在这里。三、OAuth2 的核心思想OAuth2 的核心思想是不给账号密码只给授权令牌。也就是说用户不把微信密码给你的系统。而是用户去微信那里登录 用户同意授权 微信给你的系统一个授权结果 你的系统再拿这个结果换 AccessToken你的系统拿到的不是用户密码而是一个 AccessToken。这个 AccessToken 代表用户允许你访问一部分资源例如允许读取用户头像 允许读取用户昵称 允许读取用户 openid这就是 OAuth2 的本质授权第三方应用访问用户资源。四、OAuth2 里面的四个角色OAuth2 里有四个核心角色。这四个角色非常重要。角色含义例子Resource Owner资源拥有者用户本人Client第三方应用你的 APP / 网站Authorization Server授权服务器微信授权服务器Resource Server资源服务器微信用户信息接口1. Resource Owner资源拥有者Resource Owner 就是用户本人。例如微信用户 GitHub 用户 Google 用户用户拥有自己的头像、昵称、邮箱、openid 等信息。这些信息属于用户。2. Client第三方应用Client 就是你的系统。例如你的 APP 你的网站 你的后台系统它想访问用户在微信、GitHub、Google 上的资源。注意这里的 Client 不是客户端开发里的 Android / iOS 客户端而是 OAuth2 语境里的“第三方应用”。3. Authorization Server授权服务器Authorization Server 负责让用户登录并授权。例如微信授权服务器 GitHub 授权服务器 Google 授权服务器它负责确认两件事用户是谁 用户是否同意授权4. Resource Server资源服务器Resource Server 负责保存用户资源。例如微信用户信息接口 GitHub 用户信息接口 Google 用户信息接口Client 拿到 AccessToken 后可以去资源服务器获取用户信息。五、用微信登录理解 OAuth2我们用最常见的微信登录来理解 OAuth2。流程大概是用户点击微信登录 ↓ 跳转到微信授权页面 ↓ 用户在微信完成登录 ↓ 用户同意授权 ↓ 微信返回 authorization code ↓ 你的后端用 code 换 accessToken ↓ 你的后端拿 accessToken 获取微信用户信息 ↓ 你的系统生成自己的 token ↓ 用户登录成功这里最关键的一点是微信返回的 Token不等于你系统自己的 Token。微信的 AccessToken 用于访问微信资源。你系统自己的 AccessToken 用于访问你自己的业务接口。这两个 Token 不是一回事。六、第三方登录的真实本质很多人以为微信登录 微信帮我们登录系统其实不是。更准确地说微信只是证明了这个用户在微信体系里的身份。然后你的系统根据微信返回的信息创建或绑定自己的用户。例如微信返回{ openid: o123456, nickname: 张三, avatar: https://xxx.png }你的系统会做一件事根据 openid 查询本地用户如果存在直接登录如果不存在创建新用户然后你的系统再签发自己的 Token{ accessToken: our_access_token, refreshToken: our_refresh_token }所以第三方登录的最终结果还是登录你自己的系统。OAuth2 只是帮你完成了第三方身份确认和授权。七、OAuth2 最常见的流程授权码模式OAuth2 有多种授权模式。企业里最常见、最推荐的是Authorization Code Flow也叫授权码模式。流程如下用户 ↓ 点击第三方登录 ↓ 跳转授权服务器 ↓ 用户登录并授权 ↓ 授权服务器返回 code ↓ 客户端把 code 给后端 ↓ 后端用 code 换 accessToken ↓ 后端获取用户信息 ↓ 后端生成自己的登录态这个流程是实际项目里最常见的第三方登录模式。八、为什么要先返回 code而不是直接返回 token这是 OAuth2 设计里非常关键的一点。如果授权服务器直接把 AccessToken 返回给前端例如浏览器、APP、小程序那么 Token 很容易暴露。所以更安全的方式是先返回一个临时 code。这个 code 有几个特点生命周期很短 只能使用一次 需要配合 client_id / client_secret 才能换 token真正换取 AccessToken 的动作通常由后端完成。这样安全性更高。九、OAuth2 和 JWT 是什么关系很多人会把 OAuth2 和 JWT 混在一起。其实它们不是一个层面的东西。技术解决什么问题OAuth2授权流程JWTToken 格式Redis会话控制Spring Security认证授权框架Gateway统一入口OAuth2 规定的是第三方授权流程怎么走。JWT 解决的是Token 如何表达用户身份。所以OAuth2 中的 AccessToken 可以是 JWT也可以不是 JWT。JWT 只是 Token 的一种格式。OAuth2 是一套授权协议。十、OAuth2 和普通登录有什么区别普通登录流程用户输入账号密码 ↓ 你的系统验证 ↓ 你的系统签发 TokenOAuth2 登录流程用户跳转到第三方平台 ↓ 第三方平台验证用户 ↓ 用户授权 ↓ 你的系统拿到授权结果 ↓ 你的系统创建或绑定本地用户 ↓ 你的系统签发自己的 Token区别在于普通登录的身份来源是你自己的系统。OAuth2 登录的身份来源是第三方平台。但最终用户仍然要在你的系统里建立自己的登录态。十一、OAuth2 和 OpenID Connect 的关系这里要补一个很重要的点。严格来说OAuth2 解决的是授权不是认证。也就是说OAuth2 本身主要回答的是我能不能访问用户资源而不是专门回答这个用户是谁真正标准化“登录身份认证”的是 OpenID Connect简称 OIDC。可以简单理解为OAuth2 授权 OIDC 登录认证但是在实际开发中很多平台的第三方登录都会基于 OAuth2 / OIDC 思路实现。所以平时我们说微信登录、GitHub 登录、Google 登录本质上都是通过第三方授权体系完成身份确认然后回到自己的系统里建立登录态。十二、OAuth2 中的 scope 是什么OAuth2 还有一个重要概念scope。scope 表示授权范围。例如read_user read_email read_profile意思是允许读取用户信息 允许读取邮箱 允许读取头像昵称它解决的是权限最小化问题。你的系统只是想拿用户头像就不应该拿用户通讯录。你的系统只是想拿邮箱就不应该拿用户所有数据。所以 OAuth2 不是给你无限权限而是用户授权什么 你才能访问什么十三、移动端为什么推荐 Authorization Code PKCE在移动端、单页应用这类场景里还有一个重要机制PKCE。可以简单理解为PKCE 是给授权码模式增加的一道安全校验。为什么需要因为移动端 APP 不能安全保存 client_secret。不像后端服务APP 安装在用户手机上容易被反编译。所以 OAuth2 后来推荐移动端和前端应用使用Authorization Code PKCE它的核心目的是防止授权码被拦截后被别人拿去换 Token。对于 Android / iOS 开发来说可以先记住一句话移动端第三方登录不推荐直接拿 token。 更推荐授权码模式 PKCE。这是一种更现代、更安全的方式。十四、OAuth2 在企业项目中的真实落地在企业项目中OAuth2 常见于以下几类场景。1. 第三方登录例如微信登录 QQ 登录 GitHub 登录 Google 登录 企业微信登录 钉钉登录用户不需要注册新账号可以使用已有账号登录系统。2. 开放平台授权例如你开发一个数据分析平台用户想让你的平台读取他的 GitHub 仓库信息。GitHub 不会让你知道用户密码。而是让用户授权你的应用访问仓库数据。这就是典型的开放平台授权。3. 企业内部统一身份平台公司内部可能有多个系统OA CRM ERP 财务系统 工单系统这些系统不希望各自维护账号密码。于是统一接入一个身份认证平台。这背后常常会用到OAuth2 OIDC SSO十五、OAuth2 在这个系列中的位置到这里我们再把前面几篇串一下。双 Token ↓ Token Redis ↓ JWT ↓ Spring Security ↓ Gateway ↓ OAuth2它们不是互相替代关系而是不同层面的能力。内容解决的问题双 Token登录态续签JWTToken 身份表达Redis会话可控Spring Security认证授权框架Gateway微服务统一入口OAuth2第三方授权所以 OAuth2 不是来替代 JWT 的。OAuth2 解决的是如何让第三方应用安全访问用户资源。JWT 解决的是Token 如何携带身份信息。Redis 解决的是会话如何主动控制。十六、面试怎么回答 OAuth2如果面试官问OAuth2 是什么可以这样回答OAuth2 是一种授权框架主要用于解决第三方应用在不获取用户账号密码的情况下经过用户授权后访问用户资源的问题。它的核心思想是不暴露用户密码 只发放有限权限的 AccessToken常见场景包括第三方登录 开放平台授权 企业统一身份认证OAuth2 中有四个核心角色Resource Owner资源拥有者也就是用户 Client第三方应用 Authorization Server授权服务器 Resource Server资源服务器企业中最常用的是授权码模式。用户登录并授权后授权服务器返回 code后端再用 code 换取 AccessToken然后获取用户信息最终由自己的系统生成登录态。十七、最终核心理解OAuth2 不是单纯为了登录。它真正解决的是第三方授权问题。也就是用户不把账号密码交给第三方应用 但允许第三方应用访问一部分资源第三方登录只是 OAuth2 最常见的应用场景之一。对于企业系统来说OAuth2 的价值在于不暴露用户密码 权限范围可控 用户可以取消授权 第三方系统不直接接触账号密码 适合开放平台和统一身份认证所以OAuth2 的本质不是“登录协议”而是授权协议。而第三方登录本质上是基于第三方授权结果 完成本系统登录态建立这才是 OAuth2 在企业认证体系中的真实位置。下篇预告下一篇我们继续《企业认证与安全体系八企业为什么都在用 RBAC一篇讲透权限模型设计》前面我们主要讲的是认证你是谁下一篇开始进入授权你能干什么我们将讲透RBAC 是什么 用户、角色、权限是什么关系 菜单权限怎么设计 按钮权限怎么设计 数据权限怎么设计 为什么企业后台不能到处写 if(admin)真正进入企业权限模型设计。