介绍
中央身份验证服务 (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 提供更详细的消息作为
执行流程
这里编写协议的执行流程,并给出一个图,该图使用 PlantUML插件绘制(idea有该插件),可以参考 gc-starter/doc 目录下的uml
登录流程
登出流程
Back Channel 方式登出回调报文
<samlp:LogoutRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="[RANDOM ID]"
Version="2.0"
IssueInstant="[CURRENT DATE/TIME]">
<saml:NameID>@NOT_USED@</saml:NameID>
<samlp:SessionIndex>[SESSION IDENTIFIER]</samlp:SessionIndex>
</samlp:LogoutRequest>
其中 SessionIndex为Service认证时获取到的Ticket,也是 ST
接入
客户端需要先注册到用户中心中,注册后通过编辑页面可以获取到接入的必要服务信息
千行开发框架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
如果使用千行的redis缓存包,还需要排除模板的缓存<dependency> <groupId>com.gccloud</groupId> <artifactId>gc-starter-sso-cas-rest</artifactId> <version>千行框架版本号</version> </dependency>
实现 ICasNoUserService 接口,该接口用于当CAS协议认证成功返回用户信息时,对用户名进行判断,如果当前应用没有该用户需要进行如下自定义处理,参考样例: ```java import com.gccloud.starter.common.utils.XmlUtils;<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>
@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下载
常见问题
接入可能会遇到的一些问题以及解决办法