CAS部署

作者: 俊杰的笔记 | 来源:发表于2017-04-01 17:53 被阅读4694次

    CAS 部署
    在centos部署cas 5.0.x

    准备工作:

    编辑hosts 增加 127.0.0.1 如cas.xxx.com

    https://apereo.github.io/cas/5.0.x/installation/Configuration-Properties.html

    一、证书

    使用jdk自带的工具keytool

    1.1 在/etc/cas下(因为build cas overlay时候要从该位置下找keystore),创建一条证书记录,保存到./thekeystore 别名为caskeystore

    keytool -genkey -alias caskeystore -keypass changeit -keyalg RSA -keystore thekeystore

    一条证书记录信息包含该条证书的私钥,公钥和对应的数字证书的信息。

    输入firstname和lastname时,要输入域名:如cas.xxx.com

    1.2 导出数字证书
    数字证书包含三部分信息:
    证书元数据信息,序列号,过期时间等;
    所有者信息,姓名、地区等;
    所有者公钥;相比于在keystore中的信息,没有所有者的密钥,所有者的密钥只有所有者自己知道,而此处的数字证书是要分发到公网上的。

    keytool -export -alias caskeystore -keystore thekeystore -rfc -file export.crt

    1.3. 将数字证书导入jdk.
    keytool -import -keystore {jdk.../}cacerts -file export.crt

    在centos 7, cacerts的路径为/etc/pki/ca-trust/extracted/java/cacerts

    1.4. keytool其他用法:
    keytool -list -keystore {jdk.../}cacerts

    删除
    keytool -delete -alias thekeystore -keystore cacerts

    1.5. 备注:
    数字证书的生成,分发,使用,可以放到三台机器上,
    A机器用于生成证书,作为CA,
    将A生成的数字证书导入B机器上的JRE,在B机器上的tomcat中配置(下面提到tomcat的HTTPS配置),
    在C机器上的浏览器访问B机器的tomcat,下载证书,将数字证书导入到本机的受信任的根目录证书。

    二、cas-gradle-overlay

    下载cas-gradle-overlay

    2.1 etc配置
    etc下的会在build过程中拷贝到操作系统的/etc/下
    修改配etc/cas/config/cas.properties

    cas.server.name: https://cas.h3cloudos.com:8443
    cas.server.prefix: https://cas.h3cloudos.com:8443/cas
    
    cas.adminPagesSecurity.ip=127\.0\.0\.1
    
    logging.config: file:/etc/cas/config/log4j2.xml
    # cas.serviceRegistry.config.location: classpath:/services
    

    修改etc/cas/config/log4j2.xml:
    ...name="org.apereo" level="debug"

    2.2 下载gradle到gradle/wrapper/下
    修改gradle/wrapper/gradle-wrapper.properties
    distributionUrl=gradle-3.2.1-bin.zip

    三、移除联网资源访问,提高访问速度

    执行./gradlew clean build之后,在cas/build/libs下生成war包
    解压后找到WEB-INF/classes
    里面内容是可以覆盖的。需要覆盖的内容复制到cas/src/main/resources下即可。

    查看解压后的WEB-INF/classes下的static和template内容发现,需要访问在线的很多js和css资源
    导致载入速度很慢。

    因此可以在static下新建dlc目录,将所需资源全部下载到其中,修改template中的在线资源引用。
    例如:template下的layout.html中的js引用,修改为

    <script type="text/javascript" th:src="@{/dlc/cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js}"></script>
    

    定制界面

    • 添加并修改fragments/logo.html
    • 添加并修改fragments/footer.html
    • 添加并修改casLoginView.html

    四、数据库认证配置

    4.1 增加依赖
    cas/build.gradle添加
    compile "org.apereo.cas:cas-server-support-jdbc:${project.'cas.version'}"

    4.2 以mysql为例

    新建castest库和t_admin_user表

    CREATE TABLE `t_admin_user` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `login_name` VARCHAR(255) NOT NULL COLLATE 'utf8_bin',
    `name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
    `password` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
    PRIMARY KEY (`id`),
    UNIQUE INDEX `login_name` (`login_name`)
    

    )

    4.2 配置
    默认用户名和密码配置在application.properties里
    改用数据库认证要先注释掉
    注释掉才能merge而不是删掉

    服务器存储BCRYPT加密后的值

    ##
    # CAS Authentication Credentials
    #
    # cas.authn.accept.users=casuser::Mellon
    
    cas.authn.jdbc.query[0].sql=SELECT password FROM t_admin_user WHERE login_name=?
    cas.authn.jdbc.query[0].healthQuery=SELECT 1
    cas.authn.jdbc.query[0].isolateInternalQueries=false
    cas.authn.jdbc.query[0].url=jdbc:mysql://casxxx.com:3306/castest?    
    createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    cas.authn.jdbc.query[0].failFast=true
    cas.authn.jdbc.query[0].isolationLevelName=ISOLATION_READ_COMMITTED
    cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
    cas.authn.jdbc.query[0].leakThreshold=10
    cas.authn.jdbc.query[0].propagationBehaviorName=PROPAGATION_REQUIRED
    cas.authn.jdbc.query[0].batchSize=1
    cas.authn.jdbc.query[0].user=root
    cas.authn.jdbc.query[0].ddlAuto=create-drop
    cas.authn.jdbc.query[0].maxAgeDays=180
    cas.authn.jdbc.query[0].password=123456
    cas.authn.jdbc.query[0].autocommit=false
    cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
    cas.authn.jdbc.query[0].idleTimeout=5000
    # cas.authn.jdbc.query[0].credentialCriteria=
    
    # cas.authn.jdbc.query[0].passwordEncoder.type=NONE|DEFAULT|STANDARD|BCRYPT
    # cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=
    # cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=
    # cas.authn.jdbc.query[0].passwordEncoder.secret=
    # cas.authn.jdbc.query[0].passwordEncoder.strength=16
    
    # cas.authn.jdbc.query[0].principalTransformation.suffix=
    # cas.authn.jdbc.query[0].principalTransformation.caseConversion=NONE|UPPERCASE|LOWERCASE
    # cas.authn.jdbc.query[0].principalTransformation.prefix=
    

    五、LDAP认证

    5.1 增加依赖
    cas/build.gradle添加
    compile "org.apereo.cas:cas-server-support-ldap:${project.'cas.version'}"

    5.2 配置
    # cas.authn.ldap[0].type=AD

    # cas.authn.ldap[0].ldapUrl=ldap://10.153.0.61
    # cas.authn.ldap[0].useSsl=false
    # cas.authn.ldap[0].baseDn=OU=Xxx,DC=XX,DC=xxx,DC=com
    # cas.authn.ldap[0].subtreeSearch=true
    # cas.authn.ldap[0].bindDn=CN=xxxx,OU=XD,OU=coxxrs,DC=XXX,DC=xxx,DC=com
    # cas.authn.ldap[0].bindCredential=mypassword
    
    # cas.authn.ldap[0].dnFormat=CN=%s,OU=RnD,OU=corpusers,DC=H3C,DC=xxx,DC=com
    # cas.authn.ldap[0].principalAttributeId=sAMAccountName
    # cas.authn.ldap[0].principalAttributePassword=userPassword
    

    六、服务注册

    6.1 etc/cas/config/cas.properties

    cas.serviceRegistry.config.location: classpath:/services

    匹配全部应用,仅用作测试
    cas/src/main/resources/services/HTTPSandIMAPS-10000001.json

    {
      "@class" : "org.apereo.cas.services.RegexRegisteredService",
      "serviceId" : "^(https|imaps|http)://.*",
      "name" : "HTTPS and IMAPS",
      "id" : 10000001,
      "description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
      "evaluationOrder" : 10000
    }
    
    1. 增加依赖

      compile "org.apereo.cas:cas-server-support-json-service-registry:${project.'cas.version'}"

    七、返回额外的信息

    https://apereo.github.io/cas/5.0.x/integration/Attribute-Release.html

    https://apereo.github.io/cas/5.0.x/installation/Configuring-Principal-Resolution.html

    7.1 注册服务时选择Attribute Release Policy,参考https://apereo.github.io/cas/5.0.x/integration/Attribute-Release-Policies.html

    以第六步的服务注册为例:
    增加ReturnAll策略
    {
    "@class" : "org.apereo.cas.services.RegexRegisteredService",
    "serviceId" : "^(https|imaps|http)://.*",
    "name" : "HTTPS and IMAPS",
    "id" : 10000001,
    "description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
    "evaluationOrder" : 10000,
    "attributeReleasePolicy" : {
    "@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
    }
    }

    7.2 以JDBC为例,增加配置
    https://apereo.github.io/cas/5.0.x/integration/Attribute-Resolution.html

    假定有userinfo表,

    CREATE TABLE `userinfo` (
        `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
        `email` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
        `login_name` VARCHAR(255) NOT NULL COLLATE 'utf8_bin',
        `roles` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
        `description` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin',
        PRIMARY KEY (`id`),
        UNIQUE INDEX `login_name` (`login_name`)
    )
    

    可以根据登录名查询email,description,roles等信息
    本例中最后配置了三个attribute

    cas.authn.attributeRepository.jdbc.singleRow=true
    cas.authn.attributeRepository.jdbc.requireAllAttributes=true
    cas.authn.attributeRepository.jdbc.caseCanonicalization=NONE
    cas.authn.attributeRepository.jdbc.queryType=OR
    
    cas.authn.attributeRepository.jdbc.sql=SELECT * FROM userinfo  WHERE {0}
    cas.authn.attributeRepository.jdbc.username=login_name
    cas.authn.attributeRepository.jdbc.healthQuery=SELECT 1
    cas.authn.attributeRepository.jdbc.isolateInternalQueries=false
    cas.authn.attributeRepository.jdbc.url=jdbc:mysql://cas.h3cloudos.com:3306/castest
    cas.authn.attributeRepository.jdbc.failFast=true
    cas.authn.attributeRepository.jdbc.isolationLevelName=ISOLATION_READ_COMMITTED
    cas.authn.attributeRepository.jdbc.dialect=org.hibernate.dialect.MySQLDialect
    cas.authn.attributeRepository.jdbc.leakThreshold=10
    cas.authn.attributeRepository.jdbc.propagationBehaviorName=PROPAGATION_REQUIRED
    cas.authn.attributeRepository.jdbc.batchSize=1
    cas.authn.attributeRepository.jdbc.user=root
    cas.authn.attributeRepository.jdbc.ddlAuto=update
    cas.authn.attributeRepository.jdbc.password=123456
    cas.authn.attributeRepository.jdbc.autocommit=false
    cas.authn.attributeRepository.jdbc.driverClass=com.mysql.jdbc.Driver
    cas.authn.attributeRepository.jdbc.idleTimeout=5000
    cas.authn.attributeRepository.jdbc.pool.suspension=false
    cas.authn.attributeRepository.jdbc.pool.minSize=6
    cas.authn.attributeRepository.jdbc.pool.maxSize=18
    cas.authn.attributeRepository.jdbc.pool.maxIdleTime=1000
    cas.authn.attributeRepository.jdbc.pool.maxWait=2000
    
    cas.authn.attributeRepository.attributes.email=email
    cas.authn.attributeRepository.attributes.roles=roles
    cas.authn.attributeRepository.attributes.description=description
    

    通过pac4j获取的CommonProfile中会包含email,roles和description

      private List<CommonProfile> getProfiles(final WebContext context) {
        final ProfileManager manager = new ProfileManager(context);
        List<CommonProfile> all = manager.getAll(true);
        all.forEach(e -> {
            e.getAttributes().forEach((k, v) -> System.out.println("--------: " + k + " : " + v));
        });
        return all;
    }
    
    --------: isFromNewLogin : true
    --------: authenticationDate : 2017-03-28T19:26:04.221+08:00[Asia/Shanghai]
    --------: authenticationMethod : QueryDatabaseAuthenticationHandler
    --------: roles : role1,role2
    --------: successfulAuthenticationHandlers : QueryDatabaseAuthenticationHandler
    --------: description : hellohellohello
    --------: longTermAuthenticationRequestTokenUsed : false
    --------: email : hello@hello.com
    

    八、CAS Dashboard

    https://apereo.github.io/cas/5.0.x/installation/Configuring-Monitoring.html
    https://apereo.github.io/cas/5.0.x/installation/Monitoring-Statistics.html

    endpoints.enabled=true
    endpoints.sensitive=true
    management.context-path=/status
    endpoints.restart.enabled=false
    endpoints.shutdown.enabled=false
    
    
    # IP address may be enough to protect all endpoints.
    # If you wish to protect the admin pages via CAS itself, configure the rest.
    cas.adminPagesSecurity.ip=172\.27\.11\.87
    cas.adminPagesSecurity.loginUrl=https://cas.xxx.com:8443/cas/login
    cas.adminPagesSecurity.service=https://cas.xxx.com:8443/cas/status/dashboard
    # cas.adminPagesSecurity.users=file:/etc/cas/config/adminusers.properties
    # cas.adminPagesSecurity.adminRoles=ROLE_ADMIN
    cas.adminPagesSecurity.actuatorEndpointsEnabled=true
    

    九、REST Protocol

    https://apereo.github.io/cas/5.0.x/protocol/REST-Protocol.html

    十、Docker部署

    Dockerfile(略)

    十一、HA(略)

    相关文章

      网友评论

      • b2ebd9c61aea:您好,我在“七、返回额外的信息”这一步一直没成功,没有返回想要的属性,是不是还要配置attribute-resolver.xml这个文件,请问有没有demo可以参考一下呢?
        57345757da58:你好,请问如何通过pac4j获取属性啊,我按照你的方法获取不到,但是官网上的cas-client能获取到,可以分享一下你的pac4j代码么
        xfwang_0ef1:@俊杰的简书 你好,这么设置后,客户端还是拿不到所有的属性,应该在casServiceValidationSuccess.html 文件里边设置,但是不知道怎么取值。
        俊杰的笔记:由于已经认证过了,额外信息也可以后续单独获取,如果比较多的话。
        认证时一并获取的话,按照官网文档,先在json增加attribute release policy,配置文件中
        cas.authn.attributeRepository.attributes.xxx=yyy,xxx表示最后返回的key,yyy必须是数据库表的一个字段

      本文标题:CAS部署

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