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.crt
和 idp-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
参考文档
- Ariba (Procurement) (IdP-initiated) Integration Guide
- Ariba SAML 2.0 Integration
- Configure SSO from Salesforce to WebEx
- Configuring SAML for Ariba
- Remote Authentication for Ariba On Demand:Ariba Invoice White Paper.qxd.qxd
- SAML 验证方面的常见问题
CAS 文档