最近公司要求CAS3.5.2支持saml而目前使用的版本不支持saml,因此升级成4.0.0版本,但是升级cas到cas4.0.0版本后也需要支持ldap,网上关于4.0.0版本的文章很少而支持ldap的少之又少,本人花了很长的时间整理了关于cas4集成ldap的完美解决方案的文章,如果对该文章有什么问题,欢迎在素文宅www.yoodb.com留言询问。
首先下载cas4版本,cas-server服务端,其官方下载地址:https://github.com/apereo/cas/tree/4.0.x
在cas-server-webapp工程中的pom.xml文件中,添加以下依赖关系:
<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-ldap</artifactId> <version>${cas.version}</version> </dependency>
关于ssl的方面略过(此不可以跳过),修改tomcat里面的8443端口内容,修改成如下:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="d:/keys/yoodb.keystore" <!--你的证书所放的位置--> keystorePass="password" /> <!--认证证书的密码-->
4.0.0的版本需要增加许多配置,逐步增加配置首先需要的是修改认证入口,编辑deployerConfigContext.xml文件,具体配置如下:
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager"> <constructor-arg> <map> <!-- | IMPORTANT | Every handler requires a unique name. | If more than one instance of the same handler class is configured, you must explicitly | set its name to something other than its default name (typically the simple class name). --> <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" /> <entry key-ref="ldapAuthHandler" value-ref="primaryPrincipalResolver" /> <!--新增ldap认证的入口 --> </map> </constructor-arg> <!-- Uncomment the metadata populator to allow clearpass to capture and cache the password This switch effectively will turn on clearpass. <property name="authenticationMetaDataPopulators"> <util:list> <bean class="org.jasig.cas.extension.clearpass.CacheCredentialsMetaDataPopulator" c:credentialCache-ref="encryptedMap" /> </util:list> </property> --> <!-- | Defines the security policy around authentication. Some alternative policies that ship with CAS: | | * NotPreventedAuthenticationPolicy - all credential must either pass or fail authentication | * AllAuthenticationPolicy - all presented credential must be authenticated successfully | * RequiredHandlerAuthenticationPolicy - specifies a handler that must authenticate its credential to pass --> <property name="authenticationPolicy"> <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" /> </property> </bean> <!-- Required for proxy ticket mechanism. --> <bean id="proxyAuthenticationHandler" class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" /> <!-- | TODO: Replace this component with one suitable for your enviroment. | | This component provides authentication for the kind of credential used in your environment. In most cases | credential is a username/password pair that lives in a system of record like an LDAP directory. | The most common authentication handler beans: | | * org.jasig.cas.authentication.LdapAuthenticationHandler | * org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler | * org.jasig.cas.adaptors.x509.authentication.handler.support.X509CredentialsAuthenticationHandler | * org.jasig.cas.support.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler --> <!-- Required for proxy ticket mechanism --> <bean id="proxyPrincipalResolver" class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />
然后新增ldap中的LDAP配置文件,修改deployerConfigContext.xml文件,具体代码如下:
<!-- begin --> <bean id="ldapAuthHandler" class="org.jasig.cas.authentication.LdapAuthenticationHandler" c:authenticator-ref="authenticator"> </bean> <bean id="entryResolver" class="org.jasig.cas.authentication.support.UpnSearchEntryResolver" p:connectionFactory-ref="bindPooledLdapConnectionFactory" p:baseDn="ou=users,dc=CMP" /> <bean id="authenticator" class="org.ldaptive.auth.Authenticator" c:resolver-ref="dnResolver" c:handler-ref="authHandler" p:entryResolver-ref="entryResolver"/> <bean id="dnResolver" class="org.ldaptive.auth.PooledSearchDnResolver" p:baseDn="ou=users,dc=CMP" p:allowMultipleDns="false" p:connectionFactory-ref="searchPooledLdapConnectionFactory" p:userFilter="(uid={user})" /> <bean id="searchPooledLdapConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="searchConnectionPool" /> <bean id="searchConnectionPool" parent="abstractConnectionPool" p:connectionFactory-ref="searchConnectionFactory" /> <bean id="searchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="searchConnectionConfig" /> <bean id="searchConnectionConfig" parent="abstractConnectionConfig" p:connectionInitializer-ref="bindConnectionInitializer" /> <bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler" p:connectionFactory-ref="bindPooledLdapConnectionFactory" /> <bean id="bindPooledLdapConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="bindConnectionPool" /> <bean id="bindConnectionPool" parent="abstractConnectionPool" p:connectionFactory-ref="bindConnectionFactory" /> <bean id="bindConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindConnectionConfig" /> <bean id="bindConnectionConfig" parent="abstractConnectionConfig" /> <bean id="abstractConnectionPool" abstract="true" class="org.ldaptive.pool.BlockingConnectionPool" init-method="initialize" p:poolConfig-ref="ldapPoolConfig" p:blockWaitTime="3000" p:validator-ref="searchValidator" p:pruneStrategy-ref="pruneStrategy" p:connectionFactory-ref="connectionFactory" /> <bean id="ldapPoolConfig" class="org.ldaptive.pool.PoolConfig" p:minPoolSize="3" p:maxPoolSize="10" p:validateOnCheckOut="false" p:validatePeriodically="true" p:validatePeriod="300" /> <bean id="abstractConnectionConfig" abstract="true" class="org.ldaptive.ConnectionConfig" p:ldapUrl="ldap://127.0.0.1:1389" p:connectTimeout="3000" p:connectionInitializer-ref="bindConnectionInitializer" p:useStartTLS="false" p:useSSL="false"/><!-- 取消支持ssl,默认为false --> <!-- <bean id="sslConfig" class="org.ldaptive.ssl.SslConfig"> <property name="credentialConfig"> <bean class="org.ldaptive.ssl.X509CredentialConfig" p:trustCertificates="d:/keys/yoodb.keystore" /> </property> </bean> --> <bean id="bindConnectionInitializer" class="org.ldaptive.BindConnectionInitializer" p:bindDn="cn=DMer"> <property name="bindCredential"> <bean class="org.ldaptive.Credential" c:password="123456" /> </property> </bean> <bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy" p:prunePeriod="300" p:idleTime="600" /> <bean id="searchValidator" class="org.ldaptive.pool.SearchValidator" /> <bean id="primaryPrincipalResolver" class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" p:returnNullIfNoAttributes="true" > <property name="attributeRepository" ref="attributeRepository" /> </bean> <bean id="searchControls" class="javax.naming.directory.SearchControls" p:searchScope="1" p:countLimit="2" /> <bean id="attributeRepository" class="org.jasig.cas.persondir.LdapPersonAttributeDao" p:connectionFactory-ref="searchPooledLdapConnectionFactory" p:baseDN="ou=users,dc=CMP" p:searchControls-ref="searchControls" p:searchFilter="uid={0}"> <property name="queryAttributeMapping"> <map> <entry key="username" value="uid" /> </map> </property> <property name="resultAttributeMapping"> <map> <entry key="cn" value="cn" /> <entry key="sn" value="sn" /> <entry key="city" value="city" /> <entry key="country" value="country"/> <entry key="mail" value="mail"/> <entry key="mobile" value="mobile"/> <entry key="province" value="province"/> <entry key="uid" value="uid" /> </map> </property> </bean> <!-- end -->
注意:org.jasig.services.persondir.support.ldap.LdapPersonAttributeDao 这个类的目的将Principal与后端的LDAP目录进行匹配(queryAttributeMapping属性,将Principal的username域与LDAP查询的uid属性相匹配,即queryAttributeMapping属性中必须<entry key="username" value="uid" />配置)。提供的baseDN属性要使用LDAP进行查询(uid=ldapguest) ,并且属性要从匹配的条目进行读取。 匹配到Principal属性使用resultAttributeMapping属性中的键值对——我们将LDAP的cn和sn属性匹配到有意义的名字,而description属性匹配到role属性,而role属性就是GrantedAuthorityFromAssertionAttributesUserDetailsService要进行查找的。到这一步cas4集成ldap并返回更多用户信息就完成了。
CAS4.0.0关于service的存储方式有以下几种:
1)InMemoryServiceRegistryDaoImpl
2)JsonServiceRegistryDao
3)JpaServiceRegistryDaoImpl:如果启用了oauth,因为每一个第三方都被认为是一个service,最好存储在数据库中,管理方便
4)MongoServiceRegistryDao
CAS4.0.0默认配置是使用InMemoryServiceRegistryDaoImpl,此步骤主要是将service服务存储至数据库中,如果只是cas4.0.0集成ldap并返回更多数据,上述步骤操作完之后即可此步骤省略,如果需要将service服务存储至数据库,修改deployerConfigContext.xml文件具体代码如下:
<!-- Sample, in-memory data store for the ServiceRegistry. A real implementation would probably want to replace this with the JPA-backed ServiceRegistry DAO The name of this bean should remain "serviceRegistryDao". +--> <bean class="org.jasig.cas.services.JpaServiceRegistryDaoImpl" id="serviceRegistryDao" /> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="factoryBean" p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaVendorAdapter" p:packagesToScan-ref="packagesToScan"> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${database.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.jdbc.batch_size">${database.batchSize}</prop> </props> </property> </bean> <bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource" id="dataSource" p:driverClass="${database.driverClass}" p:username="${database.user}" p:password="${database.password}" p:url="${database.url}" /> <util:list id="packagesToScan"> <value>org.jasig.cas.services</value> <value>org.jasig.cas.ticket</value> </util:list> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" id="jpaVendorAdapter" p:generateDdl="true" p:showSql="true" /> <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager" p:entityManagerFactory-ref="factoryBean" /> <bean id="auditTrailManager" class="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" /> <bean id="healthCheckMonitor" class="org.jasig.cas.monitor.HealthCheckMonitor" p:monitors-ref="monitorsList" /> <util:list id="monitorsList"> <bean class="org.jasig.cas.monitor.MemoryMonitor" p:freeMemoryWarnThreshold="10" /> <!-- NOTE The following ticket registries support SessionMonitor: * DefaultTicketRegistry * JpaTicketRegistry Remove this monitor if you use an unsupported registry. --> <bean class="org.jasig.cas.monitor.SessionMonitor" p:ticketRegistry-ref="ticketRegistry" p:serviceTicketCountWarnThreshold="5000" p:sessionCountWarnThreshold="100000" /> </util:list> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> </beans>
在cas-server-webapp工程中cas.properties文件增加关于数据库配置信息,具体配置如下:
#oracle 连接数据库配置 database.driverClass=oracle.jdbc.driver.OracleDriver database.user=admin database.password=123456 database.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl database.dialect=org.hibernate.dialect.Oracle9Dialect #mysql 连接数据库配置 #database.driverClass=com.mysql.jdbc.Driver #database.dialect=org.hibernate.dialect.MySQLDialect #database.url=jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf8 #database.user=root #database.password=123456 database.batchSize=1
呦西 (2017/07/15 21:27:23)回复
目前正在集成Ldap,之前集成Oauth2.0已经成功拉,感谢站长分享的文章。评论一下,略表感谢!
路人甲 (2017/09/25 21:26:36)回复
有问题可以留言,CAS感觉还行不错的SSO单点登录系统