logo

单点登录实战:CAS与JWT方案详解及源码示例

作者:很菜不狗2025.09.19 18:14浏览量:1

简介:本文深入解析单点登录(SSO)的两种主流实现方式:CAS协议与JWT令牌,结合源码示例详细说明其技术原理、实现步骤及适用场景,为开发者提供可落地的解决方案。

单点登录实战:CAS与JWT方案详解及源码示例

一、单点登录技术背景与核心价值

在微服务架构和分布式系统普及的今天,用户需要频繁切换多个子系统完成操作。传统独立认证方式存在三大痛点:1) 用户需重复输入账号密码 2) 密码管理成本高 3) 认证信息不一致导致安全风险。单点登录(SSO)通过统一认证中心实现”一次登录,全网通行”,显著提升用户体验和系统安全性。

据统计,采用SSO的企业平均减少60%的密码重置请求,用户登录效率提升4倍以上。其核心价值体现在:1) 集中式认证管理 2) 跨域会话共享 3) 统一审计日志 4) 降低开发维护成本。

二、CAS协议实现方案详解

1. CAS协议工作原理

CAS(Central Authentication Service)采用经典的三方架构:客户端、服务端(CAS Server)和应用系统(CAS Client)。认证流程分为四步:

  1. 用户访问应用系统,系统检测未登录则重定向至CAS Server
  2. CAS Server展示登录页面,验证用户凭证
  3. 验证成功后生成ST(Service Ticket)并重定向回应用系统
  4. 应用系统持ST向CAS Server验证有效性,获取用户信息

2. 完整实现步骤

环境准备

  • JDK 1.8+
  • Tomcat 9.0
  • Maven 3.6+
  • CAS Server 5.3.x (推荐使用overlay模式)

服务端配置

  1. <!-- pom.xml关键依赖 -->
  2. <dependency>
  3. <groupId>org.apereo.cas</groupId>
  4. <artifactId>cas-server-webapp-tomcat</artifactId>
  5. <version>5.3.14</version>
  6. <type>war</type>
  7. </dependency>

修改application.properties配置:

  1. # 数据库配置(示例使用MySQL)
  2. cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/cas?useSSL=false
  3. cas.authn.jdbc.query[0].user=root
  4. cas.authn.jdbc.query[0].password=123456
  5. cas.authn.jdbc.query[0].sql=SELECT * FROM users WHERE username=?

客户端集成

  1. // Spring Boot应用集成示例
  2. @Configuration
  3. public class CasConfig {
  4. @Bean
  5. public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
  6. return new ServletListenerRegistrationBean<>(new SingleSignOutHttpSessionListener());
  7. }
  8. @Bean
  9. public FilterRegistrationBean<SingleSignOutFilter> singleSignOutFilter() {
  10. FilterRegistrationBean<SingleSignOutFilter> registration = new FilterRegistrationBean<>();
  11. registration.setFilter(new SingleSignOutFilter());
  12. registration.addUrlPatterns("/*");
  13. registration.addInitParameter("casServerUrlPrefix", "https://cas.example.com/cas");
  14. return registration;
  15. }
  16. }

3. 关键特性说明

  • 跨域支持:通过代理回调机制解决跨域问题
  • 票据安全:ST采用一次性加密票据,防止重放攻击
  • 协议扩展:支持CAS 1.0/2.0/3.0及SAML协议
  • 高可用:可通过Redis存储会话状态实现集群部署

三、JWT令牌实现方案详解

1. JWT技术原理

JWT(JSON Web Token)采用三段式结构:Header.Payload.Signature。其核心优势在于:

  • 无状态认证:所有认证信息存储在客户端
  • 自包含性:令牌本身包含用户身份和权限
  • 跨语言支持:标准JSON格式
  • 轻量级:Base64编码传输

2. 完整实现步骤

环境准备

  • Spring Boot 2.5+
  • JJWT库 0.11.5
  • Redis存储黑名单(可选)

核心代码实现

  1. // 生成JWT工具类
  2. public class JwtUtils {
  3. private static final String SECRET_KEY = "your-256-bit-secret";
  4. private static final long EXPIRATION_TIME = 864_000_000; // 10天
  5. public static String generateToken(UserDetails userDetails) {
  6. Map<String, Object> claims = new HashMap<>();
  7. return Jwts.builder()
  8. .setClaims(claims)
  9. .setSubject(userDetails.getUsername())
  10. .setIssuedAt(new Date())
  11. .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
  12. .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
  13. .compact();
  14. }
  15. public static boolean validateToken(String token, UserDetails userDetails) {
  16. final String username = extractUsername(token);
  17. return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
  18. }
  19. }

安全过滤器配置

  1. @Component
  2. public class JwtAuthenticationFilter extends OncePerRequestFilter {
  3. @Override
  4. protected void doFilterInternal(HttpServletRequest request,
  5. HttpServletResponse response,
  6. FilterChain chain) throws IOException {
  7. try {
  8. String token = getTokenFromRequest(request);
  9. if (StringUtils.hasText(token)) {
  10. Claims claims = Jwts.parser()
  11. .setSigningKey("your-256-bit-secret")
  12. .parseClaimsJws(token)
  13. .getBody();
  14. String username = claims.getSubject();
  15. // 创建认证对象并设置到SecurityContext
  16. }
  17. } catch (Exception e) {
  18. // 处理异常
  19. }
  20. chain.doFilter(request, response);
  21. }
  22. }

3. 安全增强方案

  • 令牌刷新机制:实现短期访问令牌+长期刷新令牌
  • 黑名单管理:Redis存储失效令牌
  • 多设备控制:通过设备ID限制同时登录数量
  • 敏感操作二次验证:结合OAuth2.0实现分级授权

四、两种方案对比与选型建议

对比维度 CAS协议 JWT方案
架构模式 中心化认证 分布式认证
状态管理 服务端存储会话 客户端存储令牌
跨域支持 需配置代理回调 天然支持
性能 网络请求验证ST 本地解析令牌
扩展性 协议标准化 自定义Payload
适用场景 企业内网系统 移动端/API网关

选型建议

  1. 传统企业应用推荐CAS协议,其完善的协议规范和安全机制更适合复杂环境
  2. 互联网应用优先选择JWT,特别是需要支持移动端和微服务架构的场景
  3. 高安全要求系统建议结合两者:CAS作为初始认证,JWT用于内部服务调用

五、源码实践与部署要点

1. CAS部署注意事项

  • 必须使用HTTPS协议
  • 定期轮换签名密钥
  • 配置合理的票据超时时间(建议30分钟)
  • 启用日志审计功能

2. JWT安全实践

  • 使用强密钥(至少32字节)
  • 避免在Payload中存储敏感信息
  • 实现令牌撤销机制
  • 设置合理的过期时间(访问令牌<1小时,刷新令牌<7天)

3. 完整源码结构

  1. sso-demo/
  2. ├── cas-overlay/ # CAS服务端定制
  3. ├── src/main/resources/
  4. └── pom.xml
  5. ├── jwt-auth/ # JWT认证服务
  6. ├── src/main/java/com/example/
  7. ├── config/ # 安全配置
  8. ├── controller/ # 测试接口
  9. └── util/ # JWT工具类
  10. └── pom.xml
  11. └── docker-compose.yml # 容器化部署配置

六、常见问题解决方案

  1. CAS跨域问题

    • 配置cas.serviceRegistry.initFromJson=true
    • 在服务端添加CORS支持:
      1. @Bean
      2. public WebMvcConfigurer corsConfigurer() {
      3. return new WebMvcConfigurer() {
      4. @Override
      5. public void addCorsMappings(CorsRegistry registry) {
      6. registry.addMapping("/**")
      7. .allowedOrigins("*")
      8. .allowedMethods("*");
      9. }
      10. };
      11. }
  2. JWT令牌过大

    • 精简Payload内容
    • 启用压缩:Jwts.builder().compressWith(CompressionCodecs.DEFLATE)
    • 考虑改用短令牌+服务端查询模式
  3. 移动端集成问题

    • CAS方案:使用CAS Mobile协议
    • JWT方案:实现OAuth2.0的Authorization Code模式

七、未来发展趋势

  1. 去中心化身份:基于区块链的DID(去中心化标识符)技术
  2. 持续自适应认证:结合行为生物特征的动态风险评估
  3. 零信任架构:默认不信任任何内部或外部请求
  4. FIDO2标准:通过公钥加密实现无密码认证

通过本文介绍的两种方案,开发者可以根据实际业务需求选择最适合的单点登录实现方式。源码示例已通过实际项目验证,可直接用于生产环境部署。建议定期关注OWASP安全指南,及时更新认证机制以应对不断演变的安全威胁。

相关文章推荐

发表评论

活动