基于CAS的单点登录配置记录

原创
2013/12/10 13:46
阅读数 1K

本次配置CAS耗时1周有余,从中学到了很多东西,现将这些东西整理一下分享出来,以供后来者借鉴。

起初接到这个任务,我就开始在网上搜资料,各种帖子来看,但是效果并不是很理想,因为帖子太多了,说法太多了,而且都不是很符合自己的实际项目情况。

其中关于配置这一块我不得不提一下这个帖子,http://www.kafeitu.me/sso/2010/11/05/sso-cas-full-course.html

说得很详细,也很全面,只要不是太粗心,都能够一次通过cas的配置。


首先,这个帖子是在你对CAS有一定的了解了之后才能看懂。

大致说一下,我的项目环境,分为两个子项目,一个是php,一个是java。

PHP需要下载phpCas,https://wiki.jasig.org/display/CASC/phpCAS

java需要下载cas-client,https://wiki.jasig.org/display/CASC/CAS+Client+for+Java+3.1

至于配置的细节,官网比我所见到的帖子都更加详尽,所以可以参考官网https://wiki.jasig.org

TGT:ticket granting ticket 在用户在CAS认证成功后,CAS生成cookie,写入浏览器,同时生成一个TGT对象,放入自己的缓存,TGT对象的ID就是cookie的值。当HTTP再次请求到来时,如果传过来的有CAS生成的cookie,则CAS以此cookie值为key查询缓存中有无TGT ,如果有的话,则说明用户之前登录过,如果没有,则用户需要重新登录。

ST:service ticket ST是CAS为用户签发的访问某一service的票据。用户访问service时,service发现用户没有ST,则要求用户去CAS获取ST。用户向CAS发出获取ST的请求,如果用户的请求中包含cookie,则CAS会以此cookie值为key查询缓存中有无TGT,如果存在TGT,则用此TGT签发一个ST,返回给用户。用户凭借ST去访问service,service拿ST去CAS验证,验证通过后,允许用户访问资源。

ST的使用次数(默认一次和过期时间,TGT的过期时间在cas\WEB-INF\spring-configuration\ticketExpirationPolicies.xml里面设置。

下面是我在本次配置的过程中出现的问题及其解决方法:

1.在配置php客户端的时候,Fatal error: Call to undefined function curl_init() in D:\MYOA\webroot\CAS\Request\CurlRequest.php on line 105

解决办法:添加php_curl模块,打开php.ini的注释,然后下载相应版本的php_curl.dll及其依赖的动态链接库ssleay32.dll和libeay32.dll。

2.去掉https的认证协议,使用http协议进行认证和ticket的传输

解决方法:在cas\WEB-INF\deployConfig.xml里面将

<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient"/>

添加一个属性

<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false"/>



还有一个地方,cas\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml

修改成,

<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
		p:cookieSecure="false"//使用http进行cookie传输
		p:cookieMaxAge="3600"
		p:cookieName="CASTGC"
		p:cookiePath="/cas" />



另外,web.xml里面的casServerLoginUrl需要修改成http协议


3.在cas中使用jasypt查看认证的用户名密码是否正确

解决方法:在deployConfig.xml里面修改默认的认证方法(默认的认证方式是,用户名密码相同即通过认证),

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> 
					<property name="dataSource" ref="casDataSource" /> 
					<property name="sql" value="select SYS_USER.SU_PASSWORD from SYS_USER where lower(SYS_USER.SU_NICKNAME_CODE)=lower(?)" />  
				</bean>

使用上面这一段替换SimpleTestUsernamePasswordAuthenticationHandler,然后在配置文件中加入下面的数据源即可。



<bean id="casDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName">
		  <value>oracle.jdbc.driver.OracleDriver</value>
		</property>
		<property name="url">
		  <value>jdbc:oracle:thin:@192.168.0.141:1521:xe</value>
		</property>
		<property name="username">
		  <value>em_mip</value>
		</property>
		<property name="password">
		  <value>mip00</value>
		</property>
   </bean>



然后,下载cas-server-support-jdbc.jar的源码,进行修改,下载链接http://grepcode.com/snapshot/repo1.maven.org/maven2/org.jasig.cas/cas-server-support-jdbc/3.3.5

解压,导入到eclipse,修改QueryDatabaseAuthenticationHandler,修改后的代码如下:

/*
 * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
 * distributed with this file and available online at
 * http://www.ja-sig.org/products/cas/overview/license/
 */
package org.jasig.cas.adaptors.jdbc;

import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.jasypt.util.password.BasicPasswordEncryptor;
import org.springframework.dao.IncorrectResultSizeDataAccessException;

/**
 * Class that if provided a query that returns a password (parameter of query
 * must be username) will compare that password to a translated version of the
 * password provided by the user. If they match, then authentication succeeds.
 * Default password translator is plaintext translator.
 * 
 * @author Scott Battaglia
 * @author Dmitriy Kopylenko
 * @version $Revision: 42776 $ $Date: 2008-01-04 09:15:42 -0500 (Fri, 04 Jan 2008) $
 * @since 3.0
 */
public final class QueryDatabaseAuthenticationHandler extends
    AbstractJdbcUsernamePasswordAuthenticationHandler {

    private String sql;

    protected final boolean authenticateUsernamePasswordInternal(
        final UsernamePasswordCredentials credentials)
        throws AuthenticationException {
        final String username = credentials.getUsername();
        final String password = credentials.getPassword();
        try {
            final String dbPassword = getJdbcTemplate().queryForObject(
                this.sql, String.class, username);
            return new BasicPasswordEncryptor().checkPassword(password, dbPassword);//主要是修改了这里
        } catch (final IncorrectResultSizeDataAccessException e) {
            // this means the username was not found.
            return false;
        }
    }

    /**
     * @param sql The sql to set.
     */
    public void setSql(final String sql) {
        this.sql = sql;
    }
}



然后,把各种依赖包导到build path里面去,让项目不报错。

打成jar包,放到cas server 的lib目录下面去即可。


4.修改登录界面和登录成功的界面

解决方法:cas\WEB-INF\view\jsp\default\ui

更改:casLoginView.jsp和casGenericSuccess.jsp

登录界面需要自己去套,form表单里面有些东西是不能更改的,否则会出现不能认证的情况。值得一提的是页面的外部css或者图片是放在cas\css和cas\images下面的。贴上我的页面以供大家参考:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>EIP登录页面</title>
<style type="text/css">
	* { padding:0; margin:0;}
	.eip-login{ width: 950px; height:700px; margin:auto;background:url(images/eip_login_bg.jpg) no-repeat;}
	.eip-login-form { padding-left:684px;padding-top:353px;}
	.eip-login-form input { border:0 none;}
	.eip-login-box p { position: relative;margin-top: 10px;*margin-top:7px;margin-left: 30px;}
	.eip-position-box { height:28px;line-height: 28px;width: 170px;color:gray; position:absolute;z-index:88;top:0;left:0px;font-size: 12px;display: inline-block;padding-left: 10px;cursor: text;}
	.eip-username, .eip-password{ height: 22px; padding: 3px; line-height: 22px; width:170px;background:#f3f3f3;padding-left: 10px;}
	.eip-submit { width:229px;height:47px;background:url(images/eip_login.png) no-repeat;margin-top: 15px;cursor: pointer;}
	.eip-reset { margin-left:180px;cursor:pointer;background:#fff;}
</style>
<script type="text/javascript" src="js/jquery-1.72.js"></script>
<script type="text/javascript">
$(function(){
	$(".eip-username").focus(function(){
		var username = $(".eip-username").val();
		if( username == '请填写EIP系统帐号(或花名)'){
			$(this).val('');
		}
	});
	$(".eip-username").blur(function(){
		var username = $(".eip-username").val();
		if( username == ' '){
			$(this).val('请填写EIP系统帐号(或花名)');
		}
	});
	$(".eip-reset").click(function(){
		$("#editForm").reset();
	});
});
</script>
</head>

<body>
	
		<form:form method="post" commandName="${commandName}" htmlEscape="true" id="edit-form">
			<div class="eip-login">
				<div class="eip-login-form">
					<div class="eip-login-box">
					<p>
						<c:if test="${not empty sessionScope.openIdLocalId}">
							<strong>${sessionScope.openIdLocalId}</strong>
							<input type="hidden" id="username" name="username" value="${sessionScope.openIdLocalId}" />
						</c:if>
						<c:if test="${empty sessionScope.openIdLocalId}">
							<form:input class="eip-username"  cssErrorClass="error" id="username" value="请填写EIP系统帐号(或花名)" size="25" tabindex="1" accesskey="${userNameAccessKey}" path="username" autocomplete="false" htmlEscape="true" />
						</c:if>
					</p>
                    <p>
						<form:password class="eip-password" cssErrorClass="error" id="password" size="25" tabindex="2" path="password"  accesskey="${passwordAccessKey}" htmlEscape="true" autocomplete="off" />
					</p>
						<input type="hidden" name="lt" value="${flowExecutionKey}" />
						<input type="hidden" name="_eventId" value="submit" />

                        <div><input class="eip-submit" name="submit" accesskey="l" value="" tabindex="4" type="submit" /></div>
                        <div><input class="eip-reset" name="reset" accesskey="c" value="重置" tabindex="5" type="reset" /></div>
					</div>
				</div>
			</div>
		</form:form>
</body>
</html>




回头一看,其实整个配置也没多难,可是其中的过程却是曲折离奇。

如果大家有什么疑问可以留言,能够帮助解决的我会尽量解答的。


展开阅读全文
打赏
1
2 收藏
分享
加载中
我这边也遇到了一个问题,我这块是java项目和php项目进行CAS认证,现在是php端退出java端可以同步退出,java端退出php端无法正常退出,能否给个思路?
2015/03/20 10:29
回复
举报

引用来自“暴徒”的评论

您好,我想请教您一个问题,按照帖子写的,进行到第六步,CAS服务器初体验的时候,输入用户名和密码admin/admin,登录提示Invalid credentials是怎么回事呢?放到tomcat目录下以后我什么都没动。用的cas版本是4.0
最新版本的验证默认已经不是用户名等于密码了,在deployerConfigContext.xml 113行 使用这个登录
2015/03/20 10:27
回复
举报
nice_so博主

引用来自“Wangshengchao”的评论

您好,再跟您请教个问题,我将cas-client集成到项目中以后,启动tomcat报了一个错:
严重: Exception starting filter AutoSetUserAdapterFilter
java.lang.ClassNotFoundException: com.wsria.demo.filter.AutoSetUserAdapterFilter
从这个错误来看是缺少web.xml文件里写的AutoSetUserAdapterFilter这个过滤器,请问这个过滤器是在哪个jar包里呢?
这个jar包,,,不知道你注意到没有,com.wsria.demo.filter.AutoSetUserAdapterFilter里面的wsria,这个是那个帖子里面博主自己加的过滤器
2014/06/06 10:47
回复
举报
您好,再跟您请教个问题,我将cas-client集成到项目中以后,启动tomcat报了一个错:
严重: Exception starting filter AutoSetUserAdapterFilter
java.lang.ClassNotFoundException: com.wsria.demo.filter.AutoSetUserAdapterFilter
从这个错误来看是缺少web.xml文件里写的AutoSetUserAdapterFilter这个过滤器,请问这个过滤器是在哪个jar包里呢?
2014/06/06 10:33
回复
举报
nice_so博主

引用来自“Wangshengchao”的评论

您好,我想请教您一个问题,按照帖子写的,进行到第六步,CAS服务器初体验的时候,输入用户名和密码admin/admin,登录提示Invalid credentials是怎么回事呢?放到tomcat目录下以后我什么都没动。用的cas版本是4.0

引用来自“nice_so”的评论

初体验,,,不知道你这个问题解决没有。如果没有的话,你可以看看源码(deployConfig.xml中SimpleTestUsernamePasswordAuthenticationHandler)的验证策略,我不太清楚你是用的什么版本,不知道验证规则是否改变

引用来自“Wangshengchao”的评论

还未解决,我用的版本是4.0,deployConfig.xml中没有SimpleTestUsernamePasswordAuthenticationHandler这个验证策略了
版本已经这么高了?那我就不太清楚了,你在网上搜搜吧
2014/06/05 12:35
回复
举报

引用来自“Wangshengchao”的评论

您好,我想请教您一个问题,按照帖子写的,进行到第六步,CAS服务器初体验的时候,输入用户名和密码admin/admin,登录提示Invalid credentials是怎么回事呢?放到tomcat目录下以后我什么都没动。用的cas版本是4.0

引用来自“nice_so”的评论

初体验,,,不知道你这个问题解决没有。如果没有的话,你可以看看源码(deployConfig.xml中SimpleTestUsernamePasswordAuthenticationHandler)的验证策略,我不太清楚你是用的什么版本,不知道验证规则是否改变
还未解决,我用的版本是4.0,deployConfig.xml中没有SimpleTestUsernamePasswordAuthenticationHandler这个验证策略了
2014/06/05 12:05
回复
举报
nice_so博主

引用来自“Wangshengchao”的评论

您好,我想请教您一个问题,按照帖子写的,进行到第六步,CAS服务器初体验的时候,输入用户名和密码admin/admin,登录提示Invalid credentials是怎么回事呢?放到tomcat目录下以后我什么都没动。用的cas版本是4.0
初体验,,,不知道你这个问题解决没有。如果没有的话,你可以看看源码(deployConfig.xml中SimpleTestUsernamePasswordAuthenticationHandler)的验证策略,我不太清楚你是用的什么版本,不知道验证规则是否改变
2014/06/05 09:35
回复
举报
您好,我想请教您一个问题,按照帖子写的,进行到第六步,CAS服务器初体验的时候,输入用户名和密码admin/admin,登录提示Invalid credentials是怎么回事呢?放到tomcat目录下以后我什么都没动。用的cas版本是4.0
2014/06/04 17:50
回复
举报
nice_so博主

引用来自“Wangshengchao”的评论

port="8443" protocol="org.apache.coyote.http11.Http11Protocol" sslenabled="true" maxthreads="150" scheme="https" secure="true" clientauth="false" sslprotocol="TLS" keystorefile="D:/keys/testkey" keystorepass="changeit"
你标签的属性写错了,注意大小写,可以参考http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#SSL_Support
2014/06/04 12:19
回复
举报
您好,刚才看了一下原帖子的评论,确实是server.xml的配置问题,里面的这几个属性项必须大写:SSLEnabled="true" maxThreads="150" clientAuth="false" sslProtocol="TLS" keystoreFile="D:/keys/testkey" keystorePass="changeit"。目前已经可以正常访问了
2014/06/04 11:57
回复
举报
更多评论
打赏
15 评论
2 收藏
1
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部