这段时间研究了下CAS SSO与预控LDAP的集成,这里废话不多说,先把标准文档奉上:
https://wiki.jasig.org/display/CASUM/LDAP
我的配置也大多按照标准文档配置的,下面依次介绍我个人配置的内容。
首先,按文档“Including the Handler”要求,配置了pom.xml文件(the default is ${project.home}/cas-server-webapp/pom.xml)。
<dependency> <groupId>${project.groupId}</groupId> <artifactId>cas-server-support-ldap</artifactId> <version>${project.version}</version> </dependency>
之后的修改全部在cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml这个文件中。
接下来使用“BindLdapAuthenticationHandler”,具体用的是下面的“Typical Active Directory Configuration”中的方式。
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler" p:filter="sAMAccountName=%u" p:searchBase="cn=Users,dc=example,dc=com" p:contextSource-ref="contextSource" p:searchContextSource-ref="pooledContextSource" p:ignorePartialResultException="true" />
然后加入"contextSource"与"pooledContextSource"的bean。
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource"> <!-- DO NOT enable JNDI pooling for context sources that perform LDAP bind operations. --> <property name="pooled" value="false"/> <!-- Although multiple URLs may defined, it's strongly recommended to avoid this configuration since the implementation attempts hosts in sequence and requires a connection timeout prior to attempting the next host, which incurs unacceptable latency on node failure. A proper HA setup for LDAP directories should use a single virtual host that maps to multiple real hosts using a hardware load balancer. --> <property name="url" value="ldaps://directory.example.com" /> <!-- Manager credentials are only required if your directory does not support anonymous searches. Never provide these credentials for FastBindLdapAuthenticationHandler since the user's credentials are used for the bind operation. --> <property name="userDn" value="manager"/> <property name="password" value="your_manager_password"/> <!-- Place JNDI environment properties here. --> <property name="baseEnvironmentProperties"> <map> <!-- Three seconds is an eternity to users. --> <entry key="com.sun.jndi.ldap.connect.timeout" value="3000" /> <entry key="com.sun.jndi.ldap.read.timeout" value="3000" /> <!-- Explained at http://download.oracle.com/javase/1.3/docs/api/javax/naming/Context.html#SECURITY_AUTHENTICATION --> <entry key="java.naming.security.authentication" value="simple" /> </map> </property> </bean>
<bean id="pooledContextSource" class="org.springframework.ldap.pool.factory.PoolingContextSource" p:minIdle="${ldap.pool.minIdle}" p:maxIdle="${ldap.pool.maxIdle}" p:maxActive="${ldap.pool.maxSize}" p:maxWait="${ldap.pool.maxWait}" p:timeBetweenEvictionRunsMillis="${ldap.pool.evictionPeriod}" p:minEvictableIdleTimeMillis="${ldap.pool.idleTime}" p:testOnBorrow="${ldap.pool.testOnBorrow}" p:testWhileIdle="${ldap.pool.testWhileIdle}" p:dirContextValidator-ref="dirContextValidator" p:contextSource-ref="contextSource" /> <bean id="dirContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" p:base="" p:filter="objectclass=*"> <property name="searchControls"> <bean class="javax.naming.directory.SearchControls" p:timeLimit="1000" p:countLimit="1" p:searchScope="0" p:returningAttributes="" /> </property> </bean>
最后在“cas.properties”文件中加入连接池的参数值。
ldap.pool.minIdle=3 ldap.pool.maxIdle=5 ldap.pool.maxSize=10 # Maximum time in ms to wait for connection to become available # under pool exhausted condition. ldap.pool.maxWait=10000 # == Evictor configuration == # Period in ms at which evictor process runs. ldap.pool.evictionPeriod=600000 # Maximum time in ms at which connections can remain idle before # they become liable to eviction. ldap.pool.idleTime=1200000 # == Connection testing settings == # Set to true to enable connection liveliness testing on evictor # process runs. Probably results in best performance. ldap.pool.testWhileIdle=true # Set to true to enable connection liveliness testing before every # request to borrow an object from the pool. ldap.pool.testOnBorrow=false
以上都是我用到的标准文档中的内容,值得注意的是两点:
1、“BindLdapAuthenticationHandler”中的“searchBase”与“contextSource”中的“userDn”里边的内容要写对,可以使用AdExplorer工具连接到AD域中查看,即可得到正确的写法。
2、我个人需要使用SSL传输,所以标准文档中提到的SSL Considerations要特别注意。需要从域中导出LDAP的证书,然后导入到CAS服务器中,并且使用636端口。
贴上我在deployerConfigContext.xml使用的配置,仅供参考。
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler" p:filter="sAMAccountName=%u" p:searchBase="ou=我的公司名称,dc=XXX,dc=XXXX,dc=com" p:contextSource-ref="contextSource" p:searchContextSource-ref="pooledContextSource" p:ignorePartialResultException="true" />
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource"> <property name="pooled" value="true"/> <property name="url" value="ldaps://server ip:636/" /> <property name="userDn" value="CN=Administrator,CN=Users,DC=XXX,DC=XXX,DC=com"/> <property name="password" value="!QAZ2wsx#EDC"/> <property name="baseEnvironmentProperties"> <map> <entry key="com.sun.jndi.ldap.connect.timeout" value="3000" /> <entry key="com.sun.jndi.ldap.read.timeout" value="3000" /> <entry key="java.naming.security.authentication" value="simple" /> </map> </property> </bean> <bean id="pooledContextSource" class="org.springframework.ldap.pool.factory.PoolingContextSource" p:minIdle="${ldap.pool.minIdle}" p:maxIdle="${ldap.pool.maxIdle}" p:maxActive="${ldap.pool.maxSize}" p:maxWait="${ldap.pool.maxWait}" p:timeBetweenEvictionRunsMillis="${ldap.pool.evictionPeriod}" p:minEvictableIdleTimeMillis="${ldap.pool.idleTime}" p:testOnBorrow="${ldap.pool.testOnBorrow}" p:testWhileIdle="${ldap.pool.testWhileIdle}" p:dirContextValidator-ref="dirContextValidator" p:contextSource-ref="contextSource" /> <bean id="dirContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" p:base="" p:filter="objectclass=*"> <property name="searchControls"> <bean class="javax.naming.directory.SearchControls" p:timeLimit="1000" p:countLimit="1" p:searchScope="0" p:returningAttributes="" /> </property> </bean>
这样在登录应用系统的时候,会重定向到CAS服务器,显示登陆界面,输入域用户名/密码,即可以域用户身份登录,并达成SSO。