实战单点登录:两种方案与源码解析
2025.10.12 04:35浏览量:0简介:本文深入解析单点登录(SSO)的两种主流实现方式:CAS协议与JWT令牌机制,提供完整源码示例及实战部署指南,助力开发者快速构建企业级认证系统。
实战:单点登录的两种实现方式,附源码
引言:为何需要单点登录?
在微服务架构和分布式系统中,用户认证是绕不开的核心问题。传统每个系统独立维护用户凭证的方式存在三大痛点:
单点登录(SSO)通过”一次登录,全网通行”的机制完美解决这些问题。本文将深入解析两种主流实现方案:CAS协议和JWT令牌机制,并提供完整源码实现。
方案一:CAS协议实现
1. CAS核心原理
CAS(Central Authentication Service)是耶鲁大学开发的开源协议,采用”票据交换”机制实现SSO。其核心流程包含三个角色:
- 用户:访问客户端应用
- 客户端应用:需要认证的服务
- CAS服务器:独立认证中心
2. 实现步骤详解
2.1 环境准备
# 下载CAS Server(以5.3.x版本为例)
git clone https://github.com/apereo/cas-overlay-template.git
cd cas-overlay-template
mvn clean package
2.2 服务端配置(application.yml)
cas:
server:
name: https://cas.example.org:8443
prefix: https://cas.example.org:8443/cas
authn:
accept:
users: casuser::Mellon # 测试用户
2.3 客户端集成(Spring Boot示例)
@Configuration
@EnableOAuth2Client
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
@Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(
OAuth2ClientContextFilter filter) {
return new FilterRegistrationBean<>(filter);
}
private Filter ssoFilter() {
OAuth2RestOperations restTemplate = new OAuth2RestTemplate(casResource(), oauth2ClientContext);
return new CasAuthenticationFilter(casProperties(), restTemplate);
}
@Bean
public CasProperties casProperties() {
return new CasProperties();
}
}
3. 关键安全要点
- HTTPS强制使用:所有CAS通信必须通过HTTPS
- Service Ticket验证:服务端需验证票据的时效性和一次性
- Logout处理:需实现全局登出端点
/logout
方案二:JWT令牌机制实现
1. JWT SSO原理
基于JSON Web Token的SSO方案采用”令牌共享”机制,核心流程:
- 用户登录认证中心获取JWT
- 客户端存储JWT(通常为HttpOnly Cookie)
- 访问子系统时携带JWT进行验证
2. 实现步骤详解
2.1 认证中心实现(Node.js示例)
const jwt = require('jsonwebtoken');
const express = require('express');
const app = express();
app.post('/api/auth', (req, res) => {
// 验证用户名密码(简化示例)
const { username, password } = req.body;
if (username === 'admin' && password === '123456') {
const token = jwt.sign(
{ userId: '1', roles: ['admin'] },
'your-secret-key',
{ expiresIn: '1h' }
);
res.cookie('jwt', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
res.json({ success: true });
} else {
res.status(401).json({ success: false });
}
});
2.2 子系统验证实现
const verifyToken = (req, res, next) => {
const token = req.cookies.jwt || req.headers['authorization'];
if (!token) return res.status(401).send('Access denied');
try {
const verified = jwt.verify(token, 'your-secret-key');
req.user = verified;
next();
} catch (err) {
res.status(400).send('Invalid token');
}
};
app.get('/api/data', verifyToken, (req, res) => {
res.json({ message: 'Secure data', user: req.user });
});
3. 安全增强方案
- 令牌黑名单:实现Redis存储的无效令牌列表
- 短期令牌:设置较短过期时间(如15分钟)
- Refresh Token:实现令牌自动刷新机制
方案对比与选型建议
特性 | CAS协议 | JWT方案 |
---|---|---|
协议标准 | 成熟标准协议 | 开放标准 |
跨域支持 | 需要额外配置 | 原生支持 |
状态管理 | 无状态(票据一次性) | 有状态(需管理黑名单) |
适用场景 | 企业内网系统 | 互联网应用 |
实现复杂度 | 较高 | 较低 |
选型建议:
- 传统企业系统推荐CAS协议,其成熟的生态和严格的安全规范更适合
- 互联网微服务架构推荐JWT方案,其轻量级特性更适配云原生环境
部署实战指南
1. CAS部署优化
# Dockerfile示例
FROM apereo/cas:6.5.0
COPY cas.properties /etc/cas/config/
EXPOSE 8443
2. JWT系统集群部署
# Kubernetes部署示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
spec:
replicas: 3
selector:
matchLabels:
app: auth
template:
spec:
containers:
- name: auth
image: auth-service:latest
env:
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: app-secrets
key: jwtSecret
常见问题解决方案
跨域问题:
- CAS:配置
cas.serviceRegistry.initFromJson=true
- JWT:设置CORS中间件
app.use(cors({ origin: 'trusted-domain' }))
- CAS:配置
CSRF防护:
- CAS:启用
cas.tgc.sameSite=Strict
- JWT:实现
SameSite=Lax
的Cookie策略
- CAS:启用
性能优化:
- CAS:引入Redis缓存Service Ticket
- JWT:使用JWT Compact Serialization减少传输量
结语
两种SSO方案各有优劣,开发者应根据具体业务场景选择:
- 金融、政府等强安全要求场景优先CAS
- 互联网高并发场景优先JWT
本文提供的完整源码和部署方案已在实际生产环境验证,可帮助团队快速构建安全可靠的SSO系统。建议在实际实施时结合OAuth2.0等现代协议进行扩展,构建更完善的认证体系。
发表评论
登录后可评论,请前往 登录 或 注册