目录
摘要 1
环境 1
新建工程 1
添加依赖包 2
编写测试用例 2
编写实现代码 3
工程结构截图 5
测试与打包 5
启用定制后的登录验证 6
整合测试 7
总结 7
本文以Liferay与CAS整合为例,将CAS登录验证从输入相同的用户名/密码定制为以Liferay的用户身份进行验证。
MySQL5.0.5
JRE 1.6.0.7
Ubuntu 8.04
在进行本文示例前,请参考这里。
打开NetBeans IDE,新建Java Class Library工程:PortalAuthHandler。
从CAS中的lib下找到如下jar:
cas-server-core-3.3.jar
inspektr-core-0.7.0.jar
下载spring-core.jar(2.5.5),点这里。
将这三个jar包添加到工程PortalAuthHandler下。
在Test Packages下建立测试用例,代码如下:
package com.jinfonet.developer.portal;
import junit.framework.TestCase;
import org.jasig.cas.authentication.handler.PasswordEncoder;
/**
*
* @author 88250 <[email protected]>
*/
public final class Base64PasswordEncoderTests extends TestCase {
private final PasswordEncoder passwordEncoder = new Base64PasswordEncoder("SHA1");
public void testHashBase64Encoded() {
assertEquals("qUqP5cyxm6YcTAhz05Hph5gvu9M=", this.passwordEncoder.encode("test"));
}
public void testNullPassword() {
assertEquals(null, this.passwordEncoder.encode(null));
}
public void testInvalidEncodingType() {
final PasswordEncoder pe = new Base64PasswordEncoder("invalid encoding");
try {
pe.encode("test");
fail("exception expected.");
} catch (final Exception e) {
return;
}
}
}
这个测试用例有三个测试方法,其中HashBase64Encoded最为重要。因为在Liferay的帐户表User_中的password_字段默认是以SHA1进行加密,然后再以Base64进行编码存放的。而CAS中自带的Password Encoder只有用加密算法进行加密的步骤,没有Base64编码的步骤,所以我们要写一个带有Base64编码功能的Encoder,且必须是实现 org.jasig.cas.authentication.handler.PasswordEncoder接口的。
package com.jinfonet.developer.portal;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.inspektr.common.ioc.annotation.NotNull;
import org.jasig.cas.authentication.handler.PasswordEncoder;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;
/**
*
* @author 88250 <[email protected]>
*/
public class Base64PasswordEncoder implements PasswordEncoder {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
@NotNull
private final String encodingAlgorithm;
private String characterEncoding;
public Base64PasswordEncoder(final String encodingAlgorithm) {
this.encodingAlgorithm = encodingAlgorithm;
}
public String encode(final String password) {
if (password == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance(this.encodingAlgorithm);
if (StringUtils.hasText(this.characterEncoding)) {
messageDigest.update(password.getBytes(this.characterEncoding));
} else {
messageDigest.update(password.getBytes());
}
final byte[] digest = messageDigest.digest();
return getFormattedText(digest);
} catch (final NoSuchAlgorithmException e) {
throw new SecurityException(e);
} catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* Takes the raw bytes from the digest and formats them correct.
*
* @param bytes the raw bytes from the digest.
* @return the formatted bytes.
*/
private String getFormattedText(byte[] bytes) {
final StringBuilder buf = new StringBuilder(bytes.length * 2);
sun.misc.BASE64Encoder e = new BASE64Encoder();
final String buf2 = e.encode(bytes);
for (int j = 0; j < bytes.length; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
System.out.println("Final: " + buf2);
System.out.println(encodingAlgorithm + ": " + buf);
return buf2.toString();
}
public final void setCharacterEncoding(final String characterEncoding) {
this.characterEncoding = characterEncoding;
}
}
注意:这里,我们使用了Sun的一个受限类:BASE64Encoder。如果你自己有实现,尽量用自己的。
工程的完整结构截图如下:
单元测通过后到工程目录下的dist目录下把Build出的jar中的class文件(with package)打包到$LIFERAY_HOME/webapps/cas-web/cas-server-core-3.3.jar中。
编辑$LIFERAY_HOME/webapps/cas-web/WEB-INF/deployerConfigContext.xml文件,将
<beanclass="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"/>
替换为
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="sql" value="select password_ from User_ where screenName=?"/>
<property name="passwordEncoder" ref="base64PasswordEncoder"/>
<property name="dataSource" ref="dataSource"/>
</bean>
注意:在Liferay中最好使用screenName作为CAS验证的用户名,emailAddress是不能用的,ID方式没经过测试。
然后,在紧跟的
</list>
</property>
</bean>
后加入:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="base64PasswordEncoder"
class="com.jinfonet.developer.portal.Base64PasswordEncoder" autowire="byName">
<constructor-arg value="SHA1" />
</bean>
最后,修改在文件$LIFERAY_HOME/webapps/cas-web/WEB-INF/cas.properties中配置一下数据库连接,如下:
#database.hibernate.dialect=org.hibernate.dialect.OracleDialect
database.hibernate.dialect=org.hibernate.dialect.MySQLDialect
#database.hibernate.dialect=org.hibernate.dialect.HSQLDialect
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/lportal?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
db.username=lportal
db.password=dl88250
启动Liferay与CAS后,登录Liferay(使用非Portlet)时将自动跳转到CAS验证页面,输入用户名(your screen name)与密码后,如果登录成功,将自动跳转到你在Liferay的Home里。
本文以CAS与Liferay的整合为例,介绍了定制CAS登录验证的整个开发与配置过程,也强调了一些需要注意的地方。使用CAS实现SSO(Single Sign On)将在下一次的文章中介绍,将以CAS整合Liferay+Scarab为例给大家介绍,请大家多多给予关注哦 : )