定制CAS登录验证
转载请保留作者信息:
作者:88250
Blog:http:/blog.csdn.net/DL88250
MSN & Gmail &
QQ:DL88250@gmail.com
目录
摘要 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 <DL88250@gmail.com>
*/
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 <DL88250@gmail.com>
*/
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文件,将
<bean class="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为例给大家介绍,请大家多多给予关注哦
: )