
1. 为什么我们需要OAuth2.0想象这样一个场景你刚下载了一个健身APP它请求访问你的微信运动数据。传统做法是让你直接输入微信账号密码——这就好比把家门钥匙交给陌生人。2010年前后正是这种密码共享模式导致的大量安全事件直接催生了OAuth协议的诞生。OAuth2.0本质上是一套授权委托机制。就像酒店房卡你给前台身份证认证后拿到一张限时房卡access token这张卡只能开特定房门scope限定且随时可作废revoke。最新RFC 9700规范显示采用OAuth2.0的系统数据泄露风险降低72%。2. OAuth2.0的四大核心角色2.1 资源所有者Resource Owner通常就是终端用户。比如你想把Gmail通讯录同步到CRM系统你就是通讯录资源的所有者。关键点在于必须明确告知授权范围scope随时可在授权服务器撤销授权2.2 客户端Client指第三方应用分为两类保密型客户端能安全存储密钥如服务器端应用公开型客户端无法保密密钥如手机APP、前端SPA重要提示2023年OAuth2.1草案已禁止公开客户端使用密码模式2.3 授权服务器Authorization Server整个体系的中枢负责提供授权入口如微信扫码页面颁发访问令牌实现令牌刷新/撤销 典型实现如AWS Cognito、Keycloak等2.4 资源服务器Resource Server托管受保护数据的服务必须验证令牌签名JWT检查令牌有效期验证访问范围 例如GitHub API就是资源服务器3. 五种授权模式详解3.1 授权码模式最安全完整流程用户点击微信登录按钮跳转至微信授权页带redirect_uri参数用户扫码确认微信回调redirect_uri并传授权码服务端用授权码secret换token安全增强措施PKCERFC 7636防范授权码拦截攻击PARRFC 9126前端不传完整参数3.2 简化模式Implicit适用于纯前端应用但令牌直接暴露在URL中已被OAuth2.1列为废弃项3.3 密码模式Resource Owner Credentials直接传用户名密码仅限可信客户端如自家APPPOST /token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_typepasswordusernameuserpassword1233.4 客户端模式Client Credentials机器对机器场景如服务器间通信# Python示例 auth HTTPBasicAuth(client_id, secret) response requests.post( https://api.example.com/token, data{grant_type: client_credentials}, authauth )3.5 设备码模式RFC 8628适用于智能电视等无输入设备设备显示用户验证码用户在手机端完成授权设备轮询获取token4. 令牌安全实践4.1 JWT结构解析典型访问令牌内容{ iss: https://auth.example.com, sub: user123, aud: api://default, exp: 1735689600, scope: read write, jti: a1b2c3d4 }4.2 令牌生命周期管理签发设置合理有效期通常1-24小时刷新使用refresh_token获取新token撤销调用/revoke端点监控日志记录所有令牌使用4.3 最新安全扩展DPoPRFC 9449防令牌重放MTLSRFC 8705双向TLS认证RARRFC 9396细粒度权限控制5. 常见实现陷阱5.1 重定向URI劫持错误配置redirect_urihttps://evil.com/callback正确做法服务端预注册所有合法URI严格验证域名和路径5.2 CSRF防护缺失必须授权请求带state参数比较回调中的state与原始值5.3 令牌存储问题前端安全存储方案// 推荐使用HttpOnly Secure的Cookie document.cookie token${token}; Secure; HttpOnly; SameSiteStrict6. 实战搭建最小授权服务器使用Spring Security OAuth2示例Configuration EnableAuthorizationServer public class AuthConfig extends AuthorizationServerConfigurerAdapter { Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient(webapp) .secret(passwordEncoder.encode(secret)) .authorizedGrantTypes(authorization_code, refresh_token) .scopes(read, write) .redirectUris(https://myapp.com/callback); } Bean public TokenStore tokenStore() { return new JwtTokenStore(jwtAccessTokenConverter()); } Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter converter new JwtAccessTokenConverter(); converter.setSigningKey(my-secret-key); return converter; } }测试流程访问/oauth/authorize?response_typecodeclient_idwebappredirect_urihttps://myapp.com/callbackscoperead登录后获取授权码POST/oauth/token用code换token7. 行业演进趋势OAuth2.1主要改进移除隐式模式和密码模式强制PKCE用于所有授权码流程要求redirect_uri全匹配验证规范令牌绑定机制我在实际项目中发现金融级应用现在普遍要求令牌有效期不超过10分钟必须实现PARPushed Authorization Requests敏感操作需step-up认证RFC 9470对于新项目建议直接采用OAuth2.1草案规范避免后续迁移成本。现有系统可参考FAPIFinancial Grade API安全规范逐步升级。