D 的个人博客

全职做开源,自由职业者

  menu

定制CAS登录验证

1<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8">
2<title></title>
3<meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)">
4<style type="text/css">
5<!--
6	@page { size: 8.5in 11in; margin: 0.79in }
7	P { margin-bottom: 0.08in }
8-->
9</style>

定制CAS登录验证

转载请保留作者信息:

作者:88250

Bloghttp:/blog.csdn.net/DL88250

MSN & Gmail & QQDL88250@gmail.com

目录

摘要 1

环境 1

新建工程 1

添加依赖包 2

编写测试用例 2

编写实现代码 3

工程结构截图 5

测试与打包 5

启用定制后的登录验证 6

整合测试 7

总结 7



摘要

本文以LiferayCAS整合为例,将CAS登录验证从输入相同的用户名/密码定制为以Liferay的用户身份进行验证。



环境


在进行本文示例前,请参考这里


新建工程

打开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&amp;characterEncoding=UTF-8&amp;useFastDateParsing=false

db.username=lportal

db.password=dl88250



整合测试

启动LiferayCAS后,登录Liferay(使用非Portlet)时将自动跳转到CAS验证页面,输入用户名(your screen name)与密码后,如果登录成功,将自动跳转到你在LiferayHome里。



总结

本文以CASLiferay的整合为例,介绍了定制CAS登录验证的整个开发与配置过程,也强调了一些需要注意的地方。使用CAS实现SSO(Single Sign On)将在下一次的文章中介绍,将以CAS整合Liferay+Scarab为例给大家介绍,请大家多多给予关注哦 : )