一站式登录:揭秘CAS单点登录的原理与流程

1,090 阅读8分钟

简介

什么是单点登录

单点登录(Single Sign-On,简称SSO)是一种身份验证和授权的机制,允许用户使用一组凭据(如用户名和密码)在多个相关应用系统中进行身份验证,并在通过认证后无需重复输入凭据即可访问其他应用系统。

简单描述:一次登录后,携带登录凭证,可以在多个系统间使用,无需多次登录

什么是 CAS

CAS(Central Authentication Service),它是由美国耶鲁大学开发的一种开放源代码的企业级单点登录(Single Sign-On,简称 SSO)解决方案。

在 CAS 中,用户只需要在 CAS 服务器上进行一次登录,就可以访问所有连接到 CAS 服务器的应用,而无需再次进行身份验证。这就是所谓的单点登录。

CAS 充当认证中心,为多个应用系统提供统一的身份验证和授权服务。

简单理解 CAS 是 SSO 标准的一种实现方案

CAS 原理

基本术语

TGT(Ticket-Granting Ticket):TGT 是 CAS 中的一种票据,它是用户在登录成功后由 CAS 服务器颁发的,并用于后续的身份验证和授权。TGT 通常以加密形式存在于用户的浏览器 Cookie 中,具有一定的有效期。

TGC(Ticket-Granting Cookie):TGC 是 CAS 服务器为用户生成的一个 Cookie。它存储着用户的 TGT,并且在用户访问其他应用系统时会被发送给 CAS 服务器以验证用户的身份。 TGC 是用户与 CAS 服务器之间交互的一种方式,用于传递 TGT 并维持用户的登录状态。

ST(Service Ticket):ST 是用户向 CAS 服务器请求服务票据的结果。用户携带 TGT 向 CAS 服务器请求 ST 时,CAS 服务器会验证 TGT 的有效性,并为用户生成一个用于访问特定服务的 ST。ST 通常作为 URL 参数的形式被传递给目标应用系统,用于验证用户的身份和授权用户访问受保护的资源。

TGT 与 ST 区别?TGT 是用户登录后获得的票据。而 ST 则是针对某个业务服务,是 CAS 服务器为用户生成的用于访问特定服务的票据

基本流程

CAS 的工作流程大致如下:

image.png

  1. 用户访问一个需要身份验证的应用系统。
  2. 应用系统检测到用户未登录,将用户重定向到 CAS 服务器。
  3. 用户在CAS登录页面输入用户名和密码等凭据,如果验证通过,CAS服务器会返回一个包含TGT(Ticket Granting Ticket)的 Cookie 给用户(浏览器),然后将用户重定向到应用系统,并在重定向的 URL 中附带一个一次性的票据(ST,Service Ticket)。
  4. 用户再次访问应用服务,应用服务发现用户的请求中带有 ST,于是向 CAS 服务验证 ST 的有效性。
  5. CAS 服务器确认令牌有效后,向应用系统返回用户身份信息。
  6. 应用系统使用该身份信息创建本地会话,允许用户访问受保护的资源

这样,用户只需要在 CAS 服务器上进行一次登录,就可以访问所有参与 CAS 的应用系统,实现了单点登录。

注意:这里的应用系统,一般在网关处完成。

TGT 的作用

TGT 的主要作用是用于获取 ST(Service Ticket)。

在用户首次登录 CAS 服务器并验证通过后,CAS 服务器会生成一个 TGT,并以 Cookie 的形式存储在用户的浏览器中。

当用户访问其他应用系统时,应用系统会检查用户的请求中是否包含 TGT。如果包含,应用系统会将用户重定向到 CAS 服务器,并附带 TGT 请求一个新的ST

CAS 服务器会检查 TGT 的有效性,如果有效,CAS 服务器会为应用系统生成一个新的 ST,并将用户重定向回应用系统,同时在重定向的 URL 中附带新的 ST。

简单说:TGT 的作用在于访问其他系统时,会重定向到 CAS 服务生成特定的 ST

每一次请求都需要将 TGT 和 service 发送到 CAS 校验?

不需要。

用户只需要在首次访问应用系统时进行身份认证,之后的请求都不需要再次进行身份认证。只有当用户的会话过期或者用户主动登出时,才需要重新进行身份认证。

每个应用需要创建自己的本地会话?

一般是的。

每个应用在接收到 CAS 服务器返回的用户身份信息后,通常会在本地创建一个会话(Session),并将用户的身份信息存储在这个会话中。

这样,当用户再次访问该应用时,应用可以从本地会话中获取用户的身份信息,而无需再次向 CAS 服务器请求。

这种方式的好处是,一方面可以减少与 CAS 服务器的交互,提高系统的响应速度;另一方面,即使 CAS 服务器暂时不可用,用户仍然可以访问已经登录的应用

但是,这种方式也有一个缺点,那就是如果用户在一个应用中登出,其他应用无法知道用户已经登出。

为了解决这个问题,CAS 提供了一个登出回调接口,当用户在一个应用中登出时,该应用可以调用这个接口,通知其他应用用户已经登出。其他应用收到通知后,可以销毁本地的会话,使用户在这些应用中也处于登出状态。

当然,也可以考虑分布式 session 管理,实现会话共享

不同域下的单点登录系统流程

用户首次访问系统1登录

1.用户访问系统,用户现在没有登录。

2.跳转到 SSO 登录系统,此系统也未登录,跳转到登录页面

3.用户填写用户名/密码,SSO 系统认证后,登录态写入 SSO 的 seession,浏览器中写入cooki

4.登录完成后生成 ST,跳转到系统,ST 作为参数传递给系统

5.系统收到 ST 后,验证是否有效

6.验证成功后,登录态写入 seesion,并 set-cookie

用户再次访问系统2登录

1.用户访问系统2,未登录,跳转到 SSO。

2.SSO 已经登录,不需要重新登录认证。

3.生成 ST,跳转到系统2,参数 ST 传给系统2。

4.系统2验证 ST 是否有效。

5.验证成功后,登录态写入 seesion,并 set-cookie

为什么需要 CAS?不用行不行?

如果你的系统只有一个应用,那么可能不需要使用 CAS。用户可以直接在这个应用上进行登录,然后就可以使用这个应用的所有功能了。

但是,如果你的系统包含多个应用,而且这些应用需要共享用户的身份信息,那么没有 CAS 的话,用户在访问每个应用时都需要进行一次登录,就会给用户带来很大的不便。

而且,每个应用都需要保存用户的用户名和密码,这会增加系统被攻击的风险。

一般大型企业诉求更加明显,很多不同模块业务服务,使用不同系统(可以按网关理解),使用 CAS 就是一种很好的解决方案。

应用系统交互原理

在 Web 应用中,通常会使用过滤器(Filter)或者拦截器(Interceptor)来拦截用户的请求,并根据用户的登录状态决定是否重定向到登录页面。

1、以 Java 为例,你可以在 Servlet Filter 中进行拦截:

public class AuthenticationFilter implements Filter {
    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 || session.getAttribute("user") == null) {
            response.sendRedirect(request.getContextPath() + "/login"); // 未登录,重定向到登录页面
        } else {
            chain.doFilter(req, res); // 已登录,继续处理请求
        }
    }
}

2、在 Spring 框架中,你可以使用 HandlerInterceptor 进行拦截:

public class AuthenticationInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect(request.getContextPath() + "/login"); // 未登录,重定向到登录页面
            return false;
        } else {
            return true; // 已登录,继续处理请求
        }
    }
}

3、如果你使用的是 Shiro,那么你可以通过定义一个 Realm 来进行身份验证,并在 Shiro 的配置文件中定义相应的过滤器链来拦截用户的请求,Shiro 具体处理流程是:

  • 在 Filter 过滤器中,会检查当时是否存在登录信息,如果没有就重定向到登录页面。
  • 当用户通过 CAS 授权登录后,会继续访问应用系统,Filter 会检测到参数中的 ST(ticket票据)
  • Shiro 通过 Realm 向 CAS 服务端发起 ST 有效性校验
  • CAS 校验通过后,返回用户信息
  • Shiro session 管理器将信息存储,后续即可正常访问

总结

CAS 单点登录具有便利用户、简化集成和提升安全性等优点,但也存在单点故障、依赖性和安全风险等缺点。

同时,CAS 仅提供了单点登录的功能,并不涉及用户属性或访问控制方面的管理。