单点服务器中的CAS3.4升级到5.1.x遇到的一些问题

来源:互联网 发布:断鸿零雁记 知乎 编辑:程序博客网 时间:2024/06/01 07:58

        最近需要对公司的单点服务器进行升级,该服务器使用了开源的CAS来进行单点认证,目前使用的是CAS3.4版本,打算升级到最新的5.1.x版本。现在的版本也不是我写的,然后之前对CAS也没了解过,但问题摆在眼前了,遂马上去网上找各种资料,但网上对于最新的CAS的资料甚少,不过还是找到两篇非常不错的,会在文章末尾将链接贴出来。这篇文章既然是要记录一下在升级的过程中遇到的问题,那么就不从最开始的下载CAS overlay开始了,因为在我找到的那两篇文章中已经写的非常详细了,怎么安装,怎么配置最基本的数据库认证方式,认证返回用户信息,客户端集成和自定义,自定义验证类,都讲的非常详细。那么除此之外,我又遇到了什么比较特别的问题呢?

       先说明一下我遇到的场景,我这里只能升级服务器,不能动客户端一丁点东西,因为已经有好几十个客户端接入到了这个单点服务器上。所以这里就会有一个认证交互协议的问题存在,目前所有接入的客户端跟服务器交互用的是CAS2.0协议,CAS2.0和CAS3.0有什么区别呢?请看下面的xml代码,前者是CAS2.0协议验证票据时返回给客户端的数据,后者是CAS3.0的。

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas"> <cas:authenticationSuccess>  <cas:user>username</cas:user>  <cas:proxyGrantingTicket>PGTIOU-84678-8a9d...</cas:proxyGrantingTicket> </cas:authenticationSuccess></cas:serviceResponse>

<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">    <cas:authenticationSuccess>      <cas:user>username</cas:user>      <cas:attributes>        <cas:firstname>John</cas:firstname>        <cas:lastname>Doe</cas:lastname>        <cas:title>Mr.</cas:title>        <cas:email>jdoe@example.org</cas:email>        <cas:affiliation>staff</cas:affiliation>        <cas:affiliation>faculty</cas:affiliation>      </cas:attributes>      <cas:proxyGrantingTicket>PGTIOU-84678-8a9d...</cas:proxyGrantingTicket>    </cas:authenticationSuccess>  </cas:serviceResponse>
 两者相比较,CAS3.0多了一个属性attributes属性。

        可我用目前的客户端去接入新搭建的5.1版本的单点服务器,结果返回的是CAS2.0协议的数据,没有返回我想要的attributes属性,这是第一个问题,第二个问题是在我的场景中需要的返回数据的格式跟官网默认的也就是上面贴出来的格式还不一样,还需要修改xml的格式。经过一段时间的摸索源代码,终于找到了这两个问题的解决办法。


        第一步,重写org.apereo.cas.web.view.Cas20ResponseView类,将它改成跟org.apereo.cas.web.view.Cas30ResponseView一模一样即可,但要注意Cas20ResponseView原来的构造函数的方法签名不能变。接下来还需要重写cas/WEB-INF/classes/templates/protocol/2.0/casServiceValidationSuccess.html,这个文件是用来构造返回值协议格式的头部分,只需要将上面的文件改成跟cas/WEB-INF/classes/templates/protocol/3.0/casServiceValidationSuccess.html文件一样即可,当然也可以不一样。到此就解决了第一个问题,即CAS2.0协议不能返回attributes属性的问题。


        第二步,修改Cas20ResponseView类和Cas30ResponseView类中的putCasResponseAttributesIntoModel即可,像下面这样

    protected void putCasResponseAttributesIntoModel(final Map<String, Object> model,                                                     final Map<String, Object> attributes,                                                     final RegisteredService registeredService) {        LOGGER.debug("Beginning to encode attributes for the response");        final Map<String, Object> encodedAttributes = this.protocolAttributeEncoder.encodeAttributes(attributes, registeredService);        LOGGER.debug("Encoded attributes for the response are [{}]", encodedAttributes);        super.putIntoModel(model, CasProtocolConstants.VALIDATION_CAS_MODEL_ATTRIBUTE_NAME_ATTRIBUTES, encodedAttributes);        final List<String> formattedAttributes = new ArrayList<>(encodedAttributes.size());        LOGGER.debug("Beginning to format/render attributes for the response");        encodedAttributes.forEach((k, v) -> {            final Set<Object> values = CollectionUtils.toCollection(v);            values.forEach(value -> {                final String fmt = new StringBuilder()                .append("<cas:attribute>")                .append("<cas:name>")                .append(k)                .append("</cas:name>")                .append("<cas:value>")                .append(StringEscapeUtils.escapeXml10(value.toString().trim()))                .append("</cas:value>")                .append("</cas:attribute>")                        .toString();                LOGGER.debug("Formatted attribute for the response: [{}]", fmt);                formattedAttributes.add(fmt);            });        });        super.putIntoModel(model, CasProtocolConstants.VALIDATION_CAS_MODEL_ATTRIBUTE_NAME_FORMATTED_ATTRIBUTES, formattedAttributes);    }
其实就是修改字符串fmt,我这里修改之后客户端接收的响应xml如下:

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>    <cas:authenticationSuccess>        <cas:user>xxxxxxx</cas:user>        <cas:attributes>            <cas:attribute>            <cas:name>Email</cas:name>            <cas:value>xxxxx@xxx.com</cas:value>            </cas:attribute>            <cas:attribute>            <cas:name>isFromNewLogin</cas:name>            <cas:value>true</cas:value>            </cas:attribute>            <cas:attribute>            <cas:name>authenticationDate</cas:name>            <cas:value>2017-09-26T18:38:54.957+08:00[Asia/Shanghai]</cas:value>            </cas:attribute>            </cas:attributes>    </cas:authenticationSuccess></cas:serviceResponse>
请仔细看,xml格式跟上面官方默认的是不一样的,主要是attributes属性里面。


        到这里,我所遇到的问题就解决了。其实我在想我这种办法会有点笨,因为其实可以去找到在什么地方用了Cas20ResponseView这个类,然后直接改成使用Cas30ResponseView就可以了,这样就可以不管Cas20ResponseView了,但我实在懒得再去找了,既然问题解决了就完事。

本文章仅供参考,如有错误还请各位看官不吝赐教!


       最后将我参考的两篇博文链接贴出来,在此,对两位作者表示深深的感谢。特别是第一篇博文的作者,我在他的文章下评论很快就得了作者的回应,并且解决了我很多的疑问,非常感谢。


单点登录之实战CAS5.1.x

CAS5.1.x overlay服务搭建-单点登录
















原创粉丝点击