You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Jasig CAS客户端Web应用登出时的票据验证问题

解决CAS集成后单点登出不生效的问题

我之前也踩过CAS单点登出的坑,针对你遇到的「门户直接登出后,Web应用会话仍存在、直接访问仍能进入」的问题,给你几个实用的思路,既能实现每个请求的票据有效性验证,也能从根源完善单点登出机制:

1. 实时调用CAS验证端点,校验票据有效性

每次请求到达你的Web应用时,主动校验当前会话中的CAS票据是否有效:

  • 从用户会话中取出存储的CAS票据(比如cas_ticketcas_assertion对象)
  • 调用CAS服务器的标准验证接口(通常是/p3/serviceValidate/validate端点),传入票据和你的服务URL
  • 如果验证返回「票据失效/已吊销」,立即销毁本地会话,并重定向到CAS登录页面
  • 性能优化建议:给验证结果加缓存(比如用Redis或Guava Cache),设置1-5分钟的有效期,避免频繁请求CAS服务器,同时兼顾安全性

2. 完善CAS单点登出机制(更推荐的根源解法)

其实最理想的方式是让门户登出时主动通知你的Web应用销毁会话,这样就不用每次请求都校验了:

  • 在Web应用中配置CAS单点登出过滤器,监听CAS服务器发送的登出通知(一般是POST请求到/logout回调URL)
  • 当收到登出通知时,根据通知中的会话标识(比如sessionIdticket),找到对应的本地会话并销毁
  • 注意要确保CAS服务器和你的Web应用配置匹配:服务注册时填写正确的登出回调URL,CAS开启单点登出功能,会话标识能正确映射

3. 自定义全局拦截器/过滤器实现请求校验

在你的Web应用中编写全局拦截逻辑,对所有需要认证的请求进行拦截校验:

  • 以Java Servlet为例,写一个Filter拦截所有请求:
    public class CasTicketValidationFilter implements Filter {
        // 注入CAS验证地址和你的服务地址
        private String casValidateEndpoint;
        private String appServiceUrl;
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            HttpSession session = request.getSession(false);
    
            // 无会话直接跳转登录
            if (session == null) {
                redirectToCasLogin(response);
                return;
            }
    
            String casTicket = (String) session.getAttribute("CAS_TICKET");
            if (casTicket == null) {
                redirectToCasLogin(response);
                return;
            }
    
            // 校验票据有效性
            boolean isTicketValid = validateCasTicket(casTicket);
            if (!isTicketValid) {
                session.invalidate();
                redirectToCasLogin(response);
                return;
            }
    
            // 校验通过,继续处理请求
            chain.doFilter(req, res);
        }
    
        private boolean validateCasTicket(String ticket) {
            // 实现调用CAS验证接口的逻辑:
            // 1. 发送GET/POST请求到casValidateEndpoint,携带ticket和service参数
            // 2. 解析CAS返回的XML/JSON结果,判断票据是否有效
            // 3. 处理网络异常、超时等情况,可降级处理
            return true; // 替换为实际验证结果
        }
    
        private void redirectToCasLogin(HttpServletResponse response) throws IOException {
            String loginUrl = casValidateEndpoint + "?service=" + URLEncoder.encode(appServiceUrl, "UTF-8");
            response.sendRedirect(loginUrl);
        }
    }
    
  • 如果是Spring Boot应用,可以用HandlerInterceptor实现类似逻辑,配置更灵活

4. 关键注意事项

  • 缓存策略:缓存验证结果时,有效期要平衡安全性和性能——对安全性要求高的系统,缓存时间设短一点(比如1分钟);普通系统可以设3-5分钟
  • 异常处理:调用CAS验证接口时要处理网络故障、CAS服务器不可用的情况,比如暂时允许访问并记录日志,或者直接跳转登录
  • HTTPS通信:确保Web应用和CAS服务器之间用HTTPS传输,避免票据被窃取伪造

内容的提问来源于stack exchange,提问作者Fra83

火山引擎 最新活动