本文介绍如何安装CAS服务器,以及如何跟OpenLDAP进行搭配
下面使用环境变量CATALINA_HOME表示tomcat的安装目录,JAVA_HOME表示JAVA安装目录.
将cas-server-3.5.2-release.zip解压(假设解压到e:\cas-server-3.5.2),然后 把e:\cas-server-3.5.2\modules\cas-server-webapp-3.5.2.war拷贝到%TOMCAT_HOME%\webapps目录下,并重命名为cas-server.war.
启动tomcat, 在浏览器访问http://localhost:8080/cas-server, 应该能看到如下的页面
可以随便输入一个用户名和密码尝试登陆。当用户名和密码相同时,登陆成功
默认情况下,CAS认证服务器的单点登陆功能只能在https下使用. 在配置tomcat支持https之前,需要生成一个SSL证书。
<!-- lang: shell -->
keytool -genkey -alias mycert -keyalg RSA -keystore mykeystore.jks -dname "CN=localhost OU=dev O=ucweb L=Guangzhou ST=Guangdong C=CN" -keypass abc123 -storepass abc123
这里对上述命令的参数做一些说明:
Keytool是一个Java数据证书的管理工具。它将密钥(key)和证书(certificates)存在一个称为keystore的文件中, 称为证书库。 keytool 没有提供单独创建一个空的证书库选项。因此默认情况下,创建一个新的证书库时会要求创建一个的证书。如果所引用的keystore已经存在,在会往里面添加新的证书。请牢记证书库和证书的密码。此外,生成证书时,CN要和服务器的域名相同,如果在本地测试,则使用localhost。
可以使用如下的命令浏览一个证书库的信息:
<!-- lang: shell -->
keytool -list -keystore mykeystore.jks
或者浏览某个证书库的某个证书:
<!-- lang: shell -->
keytool -list -keystore mykeystore.jks -alias mycert -storepass abc123
如果要删除某个证书库中的证书,使用命令:
<!-- lang: shell -->
keytool -delete -alias mycert -keystore mykeystore.jks -storepass abc123
<!-- lang: shell -->
keytool -export -file server.cer -alias mycert -keystore mykeystore.jks -storepass abc123
<!-- lang: shell -->
keytool -import -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -file server.cer -alias mycert -storepass changeit
%JAVA_HOME%/jre/lib/security/cacerts
是jre自带的证书库,并且该证书库的密码是changeit. 上述命令执行时会询问”是否信任这个认证“,输入”y“确认即可
打开%CATALINA_HOME%\conf\server.xml,去掉有关SSL的那一段的注释,并需要在connector字段中加入keystorePass=“password”(password为证书库的密码),keystoreFile= “/path/to/keystore” 。这里把刚才生成的keystore文件(mykeystore.jks)复制到%CATALINA_HOME%\conf目录下, 因此最终的配置片段应该类似于:
<Connector port="8444" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystorePass="abc123" keystoreFile="mykeystore.jks"
clientAuth="false" sslProtocol="TLS" />
这里将HTTP/SSL的监听端口修改为8444,你可以指定其他的端口,只要该端口没有被占用即可。clientAuth表示当浏览器/客户端通过https访问tomcat时,tomcat是否需要浏览器/客户端提供证书。为了简化,这里暂且设置为false。
重新启动tomcat,在浏览器访问https://localhost:8444/cas-server。 此时浏览器可能会显示警告,比如chrome会显示
先选择”仍然继续“, 接着会再次出现刚才的登陆页面。注意:此时应该没了”Non Secure Connection“的警告。至此,CAS认证服务器已完成HTTP/SSL配置。
默认情况下,CAS认证服务器提供简单的身份认证,即只要用户名和密码相同,则认证通过。而在实际应用中,我们会将用户提交的数据与某个数据源(比如LDAP或MySQL)中的账号和密码进行比对,或者调用其他服务完成身份认证。当然,你也可以提供自己的身份认证实现。
打开$CATALINA_HOME/webapps/cas-server/WEB-INF/deployerConfigContext.xml,在 节点下增加一个bean节点:
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<!-- 是否允许匿名读取 -->
<property name="anonymousReadOnly" value="false" />
<!-- OpenLDAP管理员密码 -->
<property name="password" value="123456" />
<property name="pooled" value="true" />
<property name="urls">
<list>
<value>ldaps://192.168.121.130:6361/</value>
<!-- <value>ldap://192.168.121.130:389/</value> -->
</list>
</property>
<property name="userDn" value="cn=admin,dc=ggd543,dc=com" />
<property name="baseEnvironmentProperties">
<map>
<entry key="java.naming.security.protocol" value="tls"/>
<entry key="java.naming.security.authentication" value="simple"/>
</map>
</property>
</bean>
在 .. 节点内找到SimpleTestUsernamePasswordAuthenticationHandler的配置,将其注释掉,然后添加一个认证处理类:
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler">
<!-- 使用uid作为用户名 -->
<property name="filter" value="uid=%u" />
<property name="searchBase" value="ou=Tester,dc=ggd543,dc=com" />
<property name="contextSource" ref="contextSource" />
</bean>
你可以根据需要添加多个BindLdapAuthenticationHandler
假设用户账号和密码存放在test数据库的app_user表中.
<!-- lang: shell -->
create table app_user (username varchar(30), password varchar(45) , primary key (username));
insert into app_user (username,password) values ('test01','psw01');
insert into app_user (username,password) values('test02','psw02');
复制两个jar到$CATALINA_HOME/webapps/cas-server/WEB-INF/lib目录下:
打开$CATALINA_HOME/webapps/cas-server/WEB-INF/deployerConfigContext.xml,在 节点下增加一个mysql数据源:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost/test"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</bean>
改变认证方式
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="sql" value="select password from app_user where username=?" />
<property name="dataSource" ref="dataSource" />
</bean>
由此可见,在基于数据库的认证方式中,数据表是可以随意指定的,关键是提供一条查询SQL进行认证。
要提供自定义的身份认证实现,只需继承org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler
抽象类并实现authenticateUsernamePasswordInternal
方法。下面是一个参考例子:
package com.ggd543.authentication.handler;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
public class SimpleUsernameAndPasswordAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
@Override
protected boolean authenticateUsernamePasswordInternal(UsernamePasswordCredentials usernamePasswordCredentials) throws AuthenticationException {
String username =usernamePasswordCredentials.getUsername();
String password = usernamePasswordCredentials.getPassword();
return "ggd543".equalsIgnoreCase(username) && "abc123".equalsIgnoreCase(password);
}
}
在deployerConfigContext.xml中配置该自定义的认证类
<bean class="com.ggd543.authentication.handler.SimpleUsernameAndPasswordAuthenticationHandler"></bean>
这里为了演示方便,把用户名和密码硬编码到代码中。
关于SSL错误的解决办法,请看这里