介绍

中央身份验证服务 (CAS) 是用于 Web 的单点登录/单点注销协议。它允许用户访问多个应用程序,同时仅向中央 CAS 服务器应用程序提供一次他们的凭据(例如用户 ID 和密码),CAS官网

专业术语

名词 描述
Client 是指最终用户和/或网络浏览器
CAS Client 是指与Web应用程序集成并通过CAS协议与CAS服务器交互的软件组件
Cas Server 是指中央身份验证服务
Service 是指客户端尝试访问的应用程序,注册的应用服务
SSO SSO(Single Sign On)单点登录
SLO SLO(Single Logout)单次注销
TGC TGC((Ticket Granting Cookie)是Cookie的键名,存在浏览器中,在浏览器和Cas Server间通讯时使用,是Cas Server用来明确用户身份的凭证,TGC的值是编码后的,Cas Server对TGC进行反解密,可以获取到TGT对象的Key、登录客户端IP、登录浏览器信息,这些信息会进行二次校验,防止TGC泄漏带来的安全问题
TGT TGT(Ticket Granting Ticket)是Cas Server为用户签发的登录票据,拥有了TGT,用户就可以证明自己在Cas Server成功登录过。用户在Cas Server认证成功后,Cas Server生成Cookie(TGC),写入浏览器,同时生成一个TGT对象,放入自己的缓存,TGT对象的ID就是Cookie的值。当HTTP再次请求到来时,如果传过来的有Cas Server生成的Cookie,则Cas Server以此Cookie值为key查询缓存中有无TGT ,如果有的话,则说明用户之前登录过,如果没有,则用户需要重新登录
ST ST(Service Ticket)是Cas Server为用户签发的访问某一Service的票据,用户访问Service时,Service发现用户没有ST,则要求用户去Cas Server获取ST。用户向Cas Server发出获取ST的请求,如果用户的请求中包含TGC,则Cas Server会以此Cookie值为key查询缓存中有无TGT,如果存在TGT,则用此TGT签发一个ST,返回给用户。用户凭借ST去访问Service,Service拿ST去CAS验证,验证通过后,允许用户访问资源。

接口介绍

接口使用详情参考官网说明

URI 描述
/login 凭证请求者/接受者
/logout 销毁 CAS 会话(注销)
/validate 服务票验证
/serviceValidate 服务票证验证 [CAS 2.0]
/proxyValidate 服务/代理票证验证 [CAS 2.0]
/proxy 代理票务服务 [CAS 2.0]
/p3/serviceValidate 服务票证验证 [CAS 3.0]
/p3/proxyValidate 服务/代理票证验证 [CAS 3.0]

错误描述

以下为接入CAS协议可能遇到的一些错误描述

错误码 描述
INVALID_REQUEST 并非所有必需的请求参数都存在
INVALID_TICKET_SPEC 不符合验证规范的要求
UNAUTHORIZED_SERVICE_PROXY 服务无权执行代理认证
INVALID_PROXY_CALLBACK 指定的代理回调无效。为代理身份验证指定的凭据不符合安全要求
INVALID_TICKET 提供的票证无效,或者票证不是来自初始登录并且renew在验证时设置。XML 响应块的主体应该描述确切的细节
INVALID_SERVICE 提供的票证有效,但指定的服务与票证关联的服务不匹配。CAS 必须使票证无效,并且不允许将来对同一张票证进行验证
INTERNAL_ERROR 票证验证期间发生内部错误

对于所有错误代码,建议 CAS 提供更详细的消息作为XML 响应块的正文。

执行流程

这里编写协议的执行流程,并给出一个图,该图使用 PlantUML插件绘制(idea有该插件),可以参考 gc-starter/doc 目录下的uml

登录流程

CAS_UML.svg

登出流程

CAS_Logout.svg
Back Channel 方式登出回调报文

  1. <samlp:LogoutRequest
  2. xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  3. xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
  4. ID="[RANDOM ID]"
  5. Version="2.0"
  6. IssueInstant="[CURRENT DATE/TIME]">
  7. <saml:NameID>@NOT_USED@</saml:NameID>
  8. <samlp:SessionIndex>[SESSION IDENTIFIER]</samlp:SessionIndex>
  9. </samlp:LogoutRequest>

其中 SessionIndex为Service认证时获取到的Ticket,也是 ST

接入

客户端需要先注册到用户中心中,注册后通过编辑页面可以获取到接入的必要服务信息
image.png

千行开发框架1.x版本


集成 gc-starter-oauth-cas-cas30

<dependency>
  <groupId>com.gccloud</groupId>
  <artifactId>gc-starter-oauth-cas-cas30</artifactId>
  <version>千行框架版本号</version>
</dependency>

修改配置文件

cas:
    # cas登录开关
  enable: true
  # 认证中心服务信息->服务URL
  serverUrlPrefix:  http://xxx.xxx
  # 认证中心服务信息->登录URL
  serverLoginUrl: http://xxx.xxx
  # 应用服务URL
  serverName: http://xxx.xxx
  # 认证成功后,需要跳转的页面地址
  uiUrl: http://xxx.xxx

修改前端 public/config/index.js 配置文件

{
    "cas": {
        "enable": true,
        "loginUrl": "xxx",
        "logoutUrl": "xxx"
    }
}

参数介绍

  • enable:控制是否启用单点登录
  • loginUrl:应用的后端服务地址(也是baseUrl的值) + /cas/login
  • logoutUrl:复制认证中心服务信息下的登出URL + ?service= + 复制认证中心服务信息下的登录URL + ?service= + loginUrl的值

    千行开发框架2.0~2.1版本

    集成 gc-starter-sso-cas-rest
    <dependency>
    <groupId>com.gccloud</groupId>
    <artifactId>gc-starter-sso-cas-rest</artifactId>
    <version>千行框架版本号</version>
    </dependency>
    
    如果使用千行的redis缓存包,还需要排除模板的缓存
    <dependency>
    <groupId>com.gccloud</groupId>
    <artifactId>gc-starter-sso-cas-rest</artifactId>
    <version>千行框架版本号</version>
    <exclusions>
      <exclusion>
        <groupId>com.gccloud</groupId>
        <artifactId>gc-starter-plugins-cache-caffeine</artifactId>
      </exclusion>
    </exclusions>
    </dependency>
    
    实现 ICasNoUserService 接口,该接口用于当CAS协议认证成功返回用户信息时,对用户名进行判断,如果当前应用没有该用户需要进行如下自定义处理,参考样例: ```java import com.gccloud.starter.common.utils.XmlUtils;

@Service @Slf4j public class XXXNoUserServiceImpl implements ICasNoUserService {

@Resource private CasConfig casConfig; @Resource private ISysTokenService tokenService;

@Override public void handle(HttpServletRequest request, HttpServletResponse response, String ticket, String serviceResponse) { // 解析用户信息 String username = XmlUtils.getTextForElement(serviceResponse, “user”); // 接下来可以进行注册,注册用户后可以获取到用户的ID // 根据用户的ID,模拟生成token // SysTokenVO token = tokenService.create(userDTO.getId()); // 重定向到UI页面 response.sendRedirect(casConfig.getUiUrl() + “/sys/cas?token=” + token.getToken()); } }

修改配置文件
```yaml
cas:
  # 认证中心服务信息->服务URL
  serverUrlPrefix: http://xxx.xxx
  # 认证中心服务信息->登录URL
  serverLoginUrl: http://xxx.xxx
  # 应用服务URL
  service: http://xxx.xxx/cas/login
  # 认证成功后,需要跳转的页面地址
  uiUrl: http://xxx.xxx

修改前端 public/config/index.js 配置文件

{
    "cas": {
        "enable": true,
        "loginUrl": "xxx",
        "logoutUrl": "xxx"
    }
}

参数介绍

  • enable:控制是否启用单点登录
  • loginUrl:复制认证中心服务信息下的登录URL + ?service= + 上面配置文件中的cas.service地址
  • logoutUrl:复制认证中心服务信息下的登出URL + ?service= + 上一行loginUrl的值

    千行开发框架2.2版本开始

    2.2版本开始单点登录已经集成到框架中,除了不需要引入单点登录的包,其他的和2.1版本配置一样

    其他框架

    介绍非千行开发框架项目如何集成CAS协议完成单点登录

客户端Demo下载

提供CAS协议的案例下载

常见问题

接入可能会遇到的一些问题以及解决办法