上一篇
分钟实现单点登录
- 行业动态
- 2025-05-03
- 3761
采用OAuth2.0协议,配置身份提供商与客户端,通过令牌验证实现跨系统单点登录
从原理到实践的完整指南
单点登录(SSO)的核心价值
单点登录(Single Sign-On)是一种用户认证机制,允许用户在多个系统中只需一次登录即可访问所有关联资源,其核心优势包括:
- 提升用户体验:减少重复输入账号密码的繁琐操作
- 增强安全性:通过集中认证降低密码泄露风险
- 简化管理:统一权限控制和用户生命周期管理
- 降低成本:减少多系统对接的开发维护投入
技术原理与关键流程
主流SSO方案基于OAuth 2.0/OpenID Connect协议,核心流程包含以下步骤:
步骤 | 客户端(SPA) | 认证服务器 | 资源服务器 | 说明 |
---|---|---|---|---|
1 | 发起登录请求 | 返回认证页面 | 用户访问受保护资源时触发跳转 | |
2 | 验证凭证 | 用户输入账号密码完成认证 | ||
3 | 获取授权码 | 发放Token | 通过code换取Access Token | |
4 | 携带Token访问 | 验证Token | 返回资源 | 凭Token获取目标资源 |
典型技术栈组合:
- 前端:React/Vue + Axios/Fetch
- 认证服务:Keycloak/Okta + Spring Security
- 资源服务:Spring Boot + JWT解码
分钟级实现步骤
环境准备(5分钟)
# 创建Spring Boot工程 mkdir sso-demo && cd sso-demo spring init --dependencies=web,security sso-demo # 安装Keycloak docker run -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -p 8080:8080 jboss/keycloak
配置认证服务器(10分钟)
在Keycloak中创建Realm:
- 启用”Browser Flow”认证流程
- 配置Client ID为
frontend
- 设置有效Redirect URIs(如
http://localhost:8081/
) - 生成客户端密钥(用于代码交换)
前端集成(15分钟)
// 使用Vue示例 methods: { async login() { const response = await fetch('/auth/realms/master/protocol/openid-connect/auth', { method: 'POST', body: new URLSearchParams({ client_id: 'frontend', redirect_uri: window.location.origin + '/callback', response_type: 'code', scope: 'openid profile email' }) }); window.location.href = response.url; }, async callback() { const code = new URL(window.location).searchParams.get('code'); const tokenResponse = await fetch('/auth/realms/master/protocol/openid-connect/token', { method: 'POST', body: new URLSearchParams({ grant_type: 'authorization_code', code, redirect_uri: window.location.origin + '/callback', client_id: 'frontend', client_secret: 'YOUR_CLIENT_SECRET' }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(res => res.json()); localStorage.setItem('token', tokenResponse.access_token); } }
资源服务验证(10分钟)
// Spring Boot配置JWT验证 @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.oauth2ResourceServer().jwt(); http.authorizeRequests().anyRequest().authenticated(); } }
关键组件对比表
特性 | Keycloak | Okta | Authing |
---|---|---|---|
部署方式 | Docker/本地 | SaaS/PaaS | 云服务 |
免费额度 | 无限 | 每月50万次 | 每月10万次 |
自定义程度 | 高(开源) | 中等 | 低 |
国内支持 | 需自行部署 | 网络延迟 | 中文界面 |
企业集成 | 成熟 | 成熟 | 基础功能完善 |
常见问题与解决方案
Q1:生产环境如何保障Token安全?
- 强制HTTPS传输,防止中间人攻击
- 设置合理过期时间(建议<1小时)
- 开启Token刷新机制(Refresh Token)
- 存储时使用HttpOnly Cookie(后端服务)
- 前端存储需配合指纹校验(防止XSS)
Q2:跨域请求出现CORS错误怎么办?
- 在认证服务器配置跨域策略:
<!-Keycloak Cors配置示例 --> <providers> <provider id="cors" className="org.keycloak.cors.CorsHeadersFilter"/> </providers> <cors> <allowed-origins>.example.com</allowed-origins> <allow-credentials>true</allow-credentials> </cors>
- 前端请求添加凭证:
fetch('/api', { credentials: 'include', // 必须与后端配置匹配 headers: { 'Authorization': 'Bearer '