美文网首页
Apereo CAS 爬坑

Apereo CAS 爬坑

作者: Jude95 | 来源:发表于2018-11-18 22:47 被阅读523次

    心血来潮想给公司搭个单点登录系统,毕竟内网这么多系统,每个系统都一套账号密码,这样好low。CAS提供了一个统一认证服务,所有系统直接向CAS去请求登陆认证,而用户只在CAS登陆一次就够了,在大一点的公司里基本都有这种服务,叫SSO(Single sign-on)。
    找了找开源的SSO,看到了CAS,感觉挺屌的,一直在更新,就他了。然后就开始爬坑了,记录一下,免得日后忘了又爬一次。

    CAS-Overlay-Template

    这个项目很大,还需要很多自定义配置,所以不可能做成开箱即用。CAS-Overlay-Template 就是一个模板项目,clone下来, 修改配置,然后是直接跑还是打包war或者打包docker都好说。
    新版本的 CAS-Overlay-Template 已经改为Gradle编译,我喜欢Gradle。
    clone下来后,直接 先运行
    ./build.sh copy
    再运行
    ./build.sh run
    就跑起来了。

    编译配置

    跑起来个屁。
    默认是CAS 6.0版本,直接用Java11了,要跑6.0版本先去装个jdk11,配好环境。我踩坑的时候6.0还是RC版本,发现有bug就还是滚回5.3.5,配置这些东西在gradle.properties

    # Versions
    cas.version=5.3.5  // 可以改成6.0.0-rc3
    springBootVersion=2.1.0.RELEASE
    
    appServer=-tomcat
    
    gradleVersion=4.10.2
    tomcatVersion=9
    tomcatFullVersion=9.0.12
    
    group=你的组织名
    sourceCompatibility=8   // 6.0以上就改成11
    targetCompatibility=8    // 6.0以上就改成11
    
    # Location of the downloaded CAS shell JAR
    shellDir=build/libs
    
    # use without "-slim" in tag name if you want tools like jstack, adds about 100MB to image size
    baseDockerImage=openjdk:8-slim   // 6.0以上就改成11
    

    同时,还有增加几个依赖,因为CAS完全是插件化设计

        compile "org.apereo.cas:cas-server-support-jdbc:${casServerVersion}"
        compile "org.apereo.cas:cas-server-support-jdbc-drivers:${casServerVersion}"
        compile "org.apereo.cas:cas-server-support-pm:${casServerVersion}"
        compile "org.apereo.cas:cas-server-support-pm-jdbc:${casServerVersion}"
    

    然后下1个小时依赖就可以跑起来了,可喜可贺,可喜可贺。

    配置目录

    image.png

    这个目录,里面包含了所有的配置,基本上改这里面的东西就够了。

    这个配置目录是如何生效的?

    之所以先运行 ./build.sh copy 是因为

    function copy() {
        echo -e "Creating configuration directory under /etc/cas"
        mkdir -p /etc/cas/config
    
        echo -e "Copying configuration files from etc/cas to /etc/cas"
        cp -rfv ./etc/cas/* /etc/cas
    }
    

    他会把配置文件复制进系统配置目录,然后 Springboot 启动后会去读这个系统配置目录。
    另外,注意一下 src/main/jib/docker/entrypoint.sh 里面是类似 Dockerfile

    #!/bin/sh
    
    #echo -e "\nChecking java..."
    #java -version
    
    #echo -e "\nCreating CAS configuration directories..."
    mkdir -p /etc/cas/config
    mkdir -p /etc/cas/services
    
    #echo "Listing provided CAS docker artifacts..."
    #ls -R docker/cas
    
    #echo -e "\nMoving CAS configuration artifacts..."
    mv docker/cas/thekeystore /etc/cas 2>/dev/null
    mv docker/cas/config/*.* /etc/cas/config 2>/dev/null
    mv docker/cas/services/*.* /etc/cas/services 2>/dev/null
    
    #echo -e "\nListing CAS configuration under /etc/cas..."
    #ls -R /etc/cas
    
    echo -e "\nRunning CAS..."
    exec java -Xms512m -Xmx2048M -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -jar docker/cas/war/sso.war
    

    打包镜像时,也会直接把配置目录复制进镜像的系统配置目录

    build.sh

    常用操作 build.sh 都已经写好了,常用的比如

    • ./build.sh copy 复制配置到系统目录
    • ./build.sh run 运行CAS
    • ./build.sh docker 打包镜像
    • ./build.sh debug Debug CAS

    配置

    然后几乎所有的服务配置都在 cas/config/cas.properties
    一点一点的补充吧,把example.com换成自己的域名。
    下面是 5.3.5的配置,5.2.x 的配置不一样,6.0.0也不一样,文档没写,我也不写🙂。
    后文会介绍怎么去源码看当前版本的配置项

    服务地址

    cas.server.name=http://sso.example.com
    cas.server.prefix=${cas.server.name}    //要使用根Path访问,比如 http://sso.example.com 就这样。默认值是`${cas.server.name}/cas`
    server.context-path=      //对,就是空,这样就可以使用根Path访问了,默认值是 /cas
    server.port=443    // HTTPS的端口,默认8443
    cas.server.http.enabled=true    // 开启HTTP,默认只有HTTPS,而且我只知道怎么开HTTP,不知道怎么关HTTPS
    cas.server.http.port=80  // 设置HTTP端口,默认8080
    

    上面这几个配置挺操蛋的,我以为 cas.server.prefix 改了就可以 http://sso.example.com 直接访问了,结果还是要加上/cas才能访问,这个配置是假的,只是用于各种重定向url填充用。server.context-path 才是真正的 Path。

    数据库认证

    cas.authn.accept.users=        // 留空才会禁用 Static Authentication
    cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
    cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
    cas.authn.jdbc.query[0].url=jdbc:mysql://xxxxxxxxxxxxxxxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
    cas.authn.jdbc.query[0].user=xxxxxxx
    cas.authn.jdbc.query[0].password=xxxxxxxxx
    cas.authn.jdbc.query[0].sql=select * from user where name=?
    
    // 这些配置懒得讲了,网上大部分文章讲的都没问题
    cas.authn.jdbc.query[0].fieldPassword=password    
    cas.authn.jdbc.query[0].fieldExpired=expired
    cas.authn.jdbc.query[0].fieldDisabled=disabled
    cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
    cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
    cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
    

    配置数据库认证很简单。去给数据库建个表。填一下字段名和Sql,就可以了。然后跑一下试试吧

    密码管理-邮件

    CAS支持密码管理功能,直接网页上点忘记密码,就给你邮箱发重置邮件,配置比较多,坑也很多

    # 发送邮件,我用的腾讯企业邮
    spring.mail.host=smtp.exmail.qq.com
    spring.mail.port=465
    spring.mail.username=xxxxxx@example.com
    spring.mail.password=xxxxxxx
    
    # 这是腾讯企业邮的配置,其他邮箱自己配,可能有些坑,但这个不管CAS的事
    spring.mail.properties.mail.smtp.auth=true
    spring.mail.properties.mail.smtp.socketFactory.port=465
    spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
    spring.mail.properties.mail.smtp.socketFactory.fallback=false
    spring.mail.properties.mail.smtp.ssl=true
    

    密码管理-数据库

    改改自己的SQL就好了

    cas.authn.pm.enabled=true    // 开启修改密码功能
    cas.authn.pm.autoLogin=true  // 修改密码后自动登录
    cas.authn.pm.jdbc.autocommit=true  // 加就是了
    cas.authn.pm.jdbc.sqlFindEmail=SELECT email FROM user WHERE name=?
    cas.authn.pm.jdbc.sqlChangePassword=UPDATE user SET password=? WHERE name=?
    cas.authn.pm.jdbc.url=${cas.authn.jdbc.query[0].url}
    cas.authn.pm.jdbc.user=${cas.authn.jdbc.query[0].user}
    cas.authn.pm.jdbc.password=${cas.authn.jdbc.query[0].password}
    cas.authn.pm.jdbc.dialect=${cas.authn.jdbc.query[0].dialect}
    cas.authn.pm.jdbc.driverClass=${cas.authn.jdbc.query[0].driverClass}
    # 密码修改加密规则,这个必须要和原始密码加密规则一致
    cas.authn.pm.jdbc.passwordEncoder.type=${cas.authn.jdbc.query[0].passwordEncoder.type}
    cas.authn.pm.jdbc.passwordEncoder.characterEncoding=${cas.authn.jdbc.query[0].passwordEncoder.characterEncoding}
    cas.authn.pm.jdbc.passwordEncoder.encodingAlgorithm=${cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm}
    cas.authn.pm.jdbc.passwordEncoder.secret=${cas.authn.jdbc.query[0].passwordEncoder.secret}
    

    密码管理-业务配置

    cas.authn.pm.reset.mail.from=${spring.mail.username}
    cas.authn.pm.reset.mail.subject=[XXX公司 SSO系统] 重置密码
    # 邮件内容,必须要有%s,因为会生成一个连接并且带了token,否则无法打开链接,当然这个链接也和cas.server.prefix有关系
    cas.authn.pm.reset.mail.text=[季诺科技 SSO]打开以下链接重置您的密码,10分钟后失效: %s
    cas.authn.pm.reset.expirationMinutes=10  // 邮件有效期
    cas.authn.pm.reset.securityQuestionsEnabled=false    // 问题验证,我觉得这个操作很蠢,就关了
    # 8-32位,必须包含大小写字母,数字,字符。你可以填其他密码检验正则
    cas.authn.pm.policyPattern=^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,32}
    

    神坑

    路由转发环境下的IP校验

    到这里可能本地跑起来没问题了,修改密码都正常。一部署到线上就不能修改密码,从邮箱验证链接点过去,CAS每次都拒绝此次密码修改请求。为啥?
    翻了大片的源码,终于找到了原因。邮箱里收到的链接参数是加了密的,取消加密的话就很容易看出问题。

    http://sso.example.com/login?pswdrst={"jti":"ad06632d-dcee-43e0-bf0f-639150912b96","iss":"http://sso.example.com","aud":"http://sso.example.com","exp":1542541827,"iat":1542541227,"origin":"17*.17*.0.11","client":"1*.1*.97.138","sub":"jude"}

    token里包含了请求邮件验证时的客户端IP,也不知道为啥,Nginx转发后,他拿到的IP就老是不对,点击链接访问时,IP对不上他就不认这次请求。
    普通的直接部署的CAS系统,不加这个没问题。但我们的内网环境是有一台Nginx路由,所有请求都会经过他转发,就出问题。
    差点去改源码了,好在无聊翻源码时找到,CAS原来留了一手来处理这个问题。

    cas.audit.alternateClientAddrHeaderName=X-Forwarded-For
    

    添加这个配置, CAS就会从Header里读X-Forwarded-For来确认客户端IP,这样就不存在转发后IP不对的问题了。

    6.0版本的密码修改BUG

    我也不清楚6.0版本加了找回用户名这个积累功能后,为啥找回密码页面他老是发请求到找回用户名的接口上去。导致找回密码和找回用户名2个功能都不能正常工作。源码好多,对JSP无力,没细查,改回5.3.5,BUG消失,放弃6.0。

    找配置文档

    我上面的配置有很多,官网文档写的很糟,又少又老还跳来跳去,还每个版本都要改配置项(5.2.x, 5.3.x, 6.0.x都很多不一样)。
    网上大部分文档都是5.2版本的祖传配置,一开始真是恶心死我了。
    还是得自己去翻源码,先找到 CasServerProperties 这个类,他在

    image.png
    这个类就是配置的映射,还有少数注释讲了很多官方文档没说的操作。
    image.png
    照着这个类来填配置就行了。

    弃坑

    好不容易终于跑起来这个坑B玩意了,但十分不建议使用CAS,CAS优势是开放,适合二次开发。
    但十分难用......去用keycloak吧。配置简单,界面还好看。

    相关文章

      网友评论

          本文标题:Apereo CAS 爬坑

          本文链接:https://www.haomeiwen.com/subject/crxfyftx.html