CAS 集成 SAML 2.0

CAS 集成 SAML 2.0

最近在和另一个 Team 做 CAS 集成对方 SAML 协议的单点登入。遇到点坑,就记录了下来。

CAS 协议

CAS 支持客户端接入的协议非常多,有 CAS, SAML, WS-Federation, OAuth2, OpenID, OpenID Connect, REST。这之前公司的 CAS5 已经开发了 CAS 和 Rest 协议,也在考虑 ADFS 接入。SAML 是第一次尝试。

SAML

SAML(这里都是指 SAML 2.0 版本)的介绍网上很多,可以看简书的一篇介绍以及它里面的链接。

CAS 集成 SAML

CAS 支持 SAML 的集成非常简单,根据官网 SAML2 Authentication 的说明如果不考虑各种优化(如数据库存储、安全认证),只需要加上一个 maven 的依赖就行了:

<dependency>
  <groupId>org.apereo.cas</groupId>
  <artifactId>cas-server-support-saml-idp</artifactId>
  <version>${cas.version}</version>
</dependency>

启动后访问: https://cas.example.org:8443/cas/idp/metadata 就能得到 SAML 接入的 metadata,以及各种 URL 地址了。在 /etc/cas/saml 下能得到这个 metadata 的 xml 定义文件,以及各证书(目前尚不清楚 idp-encryption.crtidp-signing.crt 分别的作用,以及 cas 的证书和客户端的证书,待测试)。

SAML error

但是事情没有那么简单。如果启用了 SAML 模块,同时又启用了 JPA Service Registry,会在启动时报一个 SQL 语法错误。

Hibernate: create table SamlRegisteredService_AttributeNameFormats (SamlRegisteredService_id bigint not null, value varchar(255), key varchar(255) not null, primary key (SamlRegisteredService_id, key)) engine=MyISAM
Hibernate: alter table RegisteredServiceImpl_Props add constraint UK_i2mjaqjwxpvurc6aefjkx5x97 unique (properties_id)
2018-06-07 09:52:42,293 WARN [org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl] - <GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement>
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement

如果后台不打印 SQL,可能是设置了 showSql=false,打开 showSql 调试(默认就是打开的)

cas:
  jdbc:
    showSql: true

大致意思是创建 Saml 的服务注册相关表的时候遇到语法错误,错在有些字段名为 key,value,是 MySQL 的关键字,不能直接 SQL 里这么写,要加上反引号 ` ,方法就是在 Service Registry 的相关配置(文件 application.yml)里面加上:

cas:
  serviceRegistry:
    jpa:
      properties:
        hibernate:
          globally_quoted_identifiers: true

题外话,一般 Hibernate 配置:

hibernate.globally_quoted_identifiers=true

Spring Boot 使用 Hibernate 是加在:

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

再重启语句就被翻译成

create table SamlRegisteredService_AttributeNameFormats (SamlRegisteredService_id bigint not null, `value` varchar(255), `key` varchar(255) not null, primary key (SamlRegisteredService_id, `key`)) engine=MyISAM

就顺利执行没有报错了。

另一个小坑

想着把其他模块:Ticket、Audit 的相关 JPA 设置都加上这个反引号以防万一:

cas:
  ticket:
    registry:
      jpa: 
        properties:
          hibernate:
            globally_quoted_identifiers: true

却发现加了反而会报错,会在 Lock 表上有个报错:找不到 lockVer 字段,所以不能加。

另一个建议

把 MySQL 的驱动升级到 6.0.6,驱动类使用 driverClass: com.mysql.cj.jdbc.Driver,原来是 com.mysql.jdbc.Driver

<!-- MySQl JDBC Driver -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>6.0.6</version>
</dependency>

另一个建议2

MySQL 数据库名称标准是不能含中划线 - 的,但是用一些工具如 DBeaver 是会加上反引号加出来,会导致一些 SQL 报错,建议数据库名只用英文、数字、和下划线,不要用中划线。

jdbc:mysql://localhost:3306/cas_5_1_x?useUnicode=true&characterEncoding=UTF-8&verifyServerCertificate=false&useSSL=false&serverTimezone=CST

参考文档

CAS 文档

上篇用 starred 生成 GitHub star 的 Awesome List
下篇用 Jekyll 搭建个人博客