基于CAS实现SSO单点登录

610 阅读3分钟

SSO是什么?

  • SSO(Single Sign-On) :

    SSO 是一种 认证机制,旨在让用户只需登录一次,就可以在多个独立的系统中访问资源,而无需重复登录。它是一种 概念性解决方案,并不限定具体实现方式。

  • CAS(Central Authentication Service) :

    CAS 是一个基于 SSO 的 具体实现协议和框架。它提供了一种标准化的方式来集中用户认证,允许多个独立应用共享单一登录状态。CAS 是 SSO 的一种实现方案,但 SSO 还有其他实现方式,比如 OAuth、SAML 等。

  • OAuthOpen Authorization): OAuth 通过一种 Token(令牌)机制,允许用户授权第三方应用访问其资源,而无需共享账号密码,也是SSO的具体实现。


举例说明:

没有 SSO 的场景:

假设一个企业有以下三个系统:

  1. 邮件系统https://mail.company.com
  2. 文件管理系统https://docs.company.com
  3. 考勤系统https://attendance.company.com

如果没有 SSO,用户需要在每个系统中分别输入用户名和密码进行登录,非常麻烦。

使用 CAS 实现 SSO 的场景:

  1. 企业部署了一个 CAS 服务器:https://auth.company.com
  2. 用户访问文件管理系统时,未登录状态会被重定向到 CAS 登录页面。
  3. 用户登录后,CAS 生成 Ticket 并重定向回文件管理系统,用户登录成功。
  4. 当用户访问邮件系统或考勤系统时,不需要再次登录,这些系统会通过 CAS 验证用户登录状态并共享会话。

通过 CAS,用户只需要登录一次即可访问所有的系统。

怎么基于CAS实现SSO单点登录?

1. 用户访问受保护的页面

  • 用户操作: 用户通过浏览器访问某个受保护资源(例如 https://app.example.com/profile)。

  • 前端处理:

    • 如果用户未登录,前端会检测到没有有效的会话信息(如 token 或 session cookie)。
    • 前端将用户的请求发送到后端。

2. 后端发现用户未登录,重定向到 CAS 服务器

  • 后端处理:

    • 检查用户请求的资源是否需要认证。

    • 如果需要认证且用户未登录(没有有效的 session),后端会生成一个 CAS 登录 URL,通常形如:

      <https://cas.example.com/login?service=https://app.example.com/callback>
      
    • 参数解析:

      • https://cas.example.com/login 是 CAS 登录地址。
      • service 是用户登录成功后,CAS 服务器需要重定向回的应用地址(callback URL)。
  • 浏览器行为:

    • 后端将用户 302 重定向 到上述 URL,浏览器自动跳转到 CAS 登录页面。

3. 用户在 CAS 服务器登录

  • CAS 服务器:

    • CAS 服务器展示登录界面,用户输入用户名和密码。

    • CAS 验证用户凭据。如果验证成功:

      • CAS 服务器生成一个 Ticket,例如 ST-12345-abcdef.

      • 浏览器被 302 重定向service 参数中指定的 URL(应用的回调地址),附带 ticket 参数:

        <https://app.example.com/callback?ticket=ST-12345-abcdef>
        

4. 前端向后端传递 Ticket

  • 前端处理:

    • 浏览器重定向到回调地址时,前端通过 URL 中的 ticket 参数获取 Ticket。

    • 前端通过 API 请求将 Ticket 传递给后端:

      fetch('/api/validate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ticket: 'ST-12345-abcdef' })
      });
      

5. 后端验证 Ticket

  • 后端处理:

    • 后端收到 Ticket 后,向 CAS 服务器的 Ticket 验证接口发起请求:

      <https://cas.example.com/serviceValidate?service=https://app.example.com/callback&ticket=ST-12345-abcdef>
      
    • CAS 服务器校验该 Ticket 是否有效,并返回验证结果:

      <cas:serviceResponse xmlns:cas="<http://www.yale.edu/tp/cas>">
        <cas:authenticationSuccess>
          <cas:user>username</cas:user>
        </cas:authenticationSuccess>
      </cas:serviceResponse>
      
    • 如果验证成功,后端创建一个本地会话(session),记录用户信息,并生成一个 token。


6. 后端向前端返回登录成功信息

  • 后端处理:

    • 将本地生成的 token 返回给前端,用于后续 API 请求认证。
    • 前端通过存储 token(如存储在 localStorage 或设置 cookie)完成登录态管理。

7. 前端重定向用户到原始页面

  • 前端处理:

    • 登录成功后,前端根据用户的请求上下文或后端返回的重定向信息,导航到用户想访问的页面。