使用Apereo Cas 5.1.3的Restful接口实现SSO及TGC分析

使用Apereo Cas 5.1.3的Restful接口实现SSO及TGC分析关于CAS的认证原理,网上已有很多相关文章了,官方文档也有说明,这里就不再详述了。本文重在阐述使用Apereo Cas 5.1.3遇到的与TGC相关的问题,及问题的分析解决过程。
摘要由CSDN通过智能技术生成

关于CAS的认证原理,网上已有很多相关文章了,官方文档也有说明,这里就不再详述了。本文重在阐述使用Apereo Cas 5.1.3遇到的与TGC相关的问题,及问题的分析解决过程。

遇到的TGC相关的问题:

  1. 由于需要使用云环境,把cas部署在了华为云上,配置了负载均衡(未启用负载均衡的会话保持),结果登陆状态无法保持,经过查看cas的日志,发现第二次访问的时候,请求的源IP与第一次访问的源IP不一致,被CAS拒绝了。华为云上的负载均衡器是一个集群,对内有多个内网IP,导致出现该问题,启用ELB的会话保持,暂时避开了此问题。
  2. 为了实现CAS集群,实现CAS无状态化,需要把CAS的session、TGT存在外部缓存redis中。实现之后,发现浏览器端的Cookie有一个TGC的值,会话状态是靠TGC保持的(即使删除SessionID,只要TGC存在就能保持登录状态)。在redis中却没发现TGC的踪迹。TGC还存储在CAS程序中?如果是,那么会话状态还是在应用实例中保持的,没有实现将所有状态信息放到程序外部。
  3. 一些业务系统需要有自己的登陆页面,在自己的登陆页面中调用CAS的Restful接口进行登录,同时又希望登录后,再访问其他使用CAS单点登录的系统时,不用再次登录。使用CAS的Restful接口进行登录认证倒容易实现,但再访问其他使用CAS单点登录的系统时,不用再次登录却没法按照CAS官方资料实现。经过分析,主要是由于业务系统使用自己的登陆页面登陆后,没有在CAS的域下写入TGC的Cookie值。要解决这个问题就需要弄清楚TGC的生成及使用逻辑,不得不去了解TGC的来龙去脉了。

解决问题的过程:

通过堆栈信息,顺利找到了CAS页面登录,表单提交的Action : SendTicketGrantingTicketAction,顺藤摸瓜,在doExecute方法中找到了调用CookieRetrievingCookieGeneratoraddCookie相关方法:

this.ticketGrantingTicketCookieGenerator.addCookie(request, response, ticketGrantingTicketId);

在addCookie方法中找到了构造cookie的相关方法:

final String theCookieValue = this.casCookieValueManager.buildCookieValue(cookieValue, request);

CookieValueManager有两个实现类:DefaultCasCookieValueManagerNoOpCookieValueManager。在Debug过程中,发现使用的是DefaultCasCookieValueManager实现类,查看它的buildCookieValue方法:

    @Override
    public String buildCookieValue(final String givenCookieValue, final HttpServletRequest request) {
        final ClientInfo clientInfo = ClientInfoHolder.getClientInfo();
        final StringBuilder builder = new StringBuilder(givenCookieValue)
                .append(COOKIE_FIELD_SEPARATOR)
                .append(clientInfo.getClientIpAddress());

        final String userAgent = WebUtils.getHttpServletRequestUserAgent(request);
        if (StringUtils.isBlank(userAgent)) {
            throw new IllegalStateException("Request does not specify a user-agent");
        }
        builder.append(COOKIE_FIELD_SEPARATOR).append(userAgent);

        final String res = builder.toString();
        LOGGER.debug("Encoding cookie value [{}]", res);
        return this.cipherExecutor.encode(res);
    }

逻辑很简单,方法传入的givenCookieValue的值其实就是TGT的值,把TGT的值使用分隔符附加上客户端IP地址、客户端代理信息(浏览器信息),编码后就得到了TGC的值。
例如:
加密前的值:

TGT-1-VOscp5EQosRdeRJK1vIIHwFCkFOeoHIqTnggPCqJ67TdqbWLi3-yh-PC@0:0:0:0:0:0:0:1@Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0

加密后的值,即客户端浏览器中存储的TGC Cookie的值:

eyJhbGciOiJIUzUxMiJ9.WlhsS05tRllRV2xQYVVwRlVsVlphVXhEU21oaVIyTnBUMmxLYTJGWVNXbE1RMHBzWW0xTmFVOXBTa0pOVkVrMFVUQktSRXhWYUZSTmFsVXlTVzR3TGk1NVJubEpjblpHWVZOR1Z5MVhURjg1UkVweWMzaFJMblI2TUZSRVpVSktjVWwxU1RkWVdGbFdkVk5uZEhkM2NHTlhXbWQwZFc1NlVVSnBUbEJGVkRWaVpYUktPREJGUTBGTExVbDZTR2Q2WlVwMFF6WTRPVTgzWmt4RVQyTjVaVkZZZGpRdFowSnllR1kzYW14MGJUYzRNMVJ5WmpGcmFITmxXbGt3WkVaM0xURkVTMjR6WHpVdFlqWnFUVTFCTVVsUk9FZ3RValkxTlZWclQzZEtNWFI2V1U5U1pFcGtaVk4yZEZSaVkyRmhaMGRFVlVodFUyOXVaSEJIT0RWdlptTkZhek5sYlVsSmVrZHBaMkp4VkZZeE4yY3pWRlZxY2k1Rk0wODNiMHAxY0ZOV1dVRm1SMjFOZDBSRFpEWjM.pZlVEOYioDF9_DJjlmOSTvWJ--WJOJe3dFQpAJRHXwH35XYXPNgcsfQ6NQ-1xoBb_-whvsOdCx68yQNdSWTyYQ

那么TGC的值在服务端是存储在哪里的呢?答案是没有存储。因为浏览器再次发送请求时,会传输来Cookie的值(即从客户端请求中获取TGC),解密TGC的值就获取了对应的TGT信息。看一下该类中对应的获取cookie的方法obtainCookieValue

    @Override
    public String obtainCookieValue(final Cookie cookie, final HttpServletRequest request) {
        
  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值