基于cas3.5.2 sever改造而成。
通过子系统页面登录:
<!DOCTYPE html PUBLIC "">
<html>
<head>
<meta name="keywords" content=""/>
<meta name="description" content=""/>
<meta http-equiv="x-ua-compatible" content="IE=edge,chrome=1"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>领御教育云 - 首页</title>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<link rel="stylesheet" type="text/css" href="css/lrtk.css"/>
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/lrtk.js"></script>
<script type="text/javascript">
function prepareLoginForm() {
//该链接https://bb.gstoneg.com:8082 一定要写成域名,如果换成服务器ip地址 即192.168.1.108只会登录cas 登录成功页面,不会跳转到我们要的service首页(也就是http://192.168.1.108:8080/PortalSite/caslogin/login.jsp)
$$('myLoginForm').action ="https://bb.gstoneg.com:8082/cas/login?service=http://192.168.1.108:8080/PortalSite/caslogin/login.jsp";
$$("lt").value = loginTicket;
}
function checkForLoginTicket() {
var loginTicketProvided = false;
var query = '';
casLoginURL = 'https://bb.gstoneg.com:8082/cas/login';
thisPageURL = 'http://192.168.1.108:8080/PortalSite/index.html';
casLoginURL += '?login-at=' + encodeURIComponent (thisPageURL);
query = window.location.search;
queryquery = query.substr (1);
var param = new Array();
var temp = new Array();
param = query.split ('&');
i = 0;
// 开始获取当前 url 的参数,获到 lt 和 error_message。
while (param[i]) {
temp= param[i].split ('=');
if (temp[0] == '?lt') {
loginTicket = temp[1];
loginTicketProvided = true;
}
if (temp[0] == 'error_message') {
error = temp[1];
}
i++;
}
// 判断是否已经获取到 lt 参数,如果未获取到则跳转至 cas/login 页,并且带上请求参数 get-lt=true。 第一次进该页面时会进行一次跳转
if (!loginTicketProvided) {
location.href = casLoginURL + '&get-lt=true&service=http://192.168.1.108:8080/PortalSite/caslogin/login.jsp';
}
}
var $$ = function(id){
return document.getElementById(id);
}
checkForLoginTicket();
onload = prepareLoginForm;
</script>
</head>
<body>
<div style="height:180px; background:#f5f5f5;">
<div style="width:1000px;height:180px;margin:0 auto;">
<div style="width:370px;height:180px; float:left;">
<img src="images/logo.jpg" style="margin-top:35px;"/>
</div>
<div style="width:630px;height:180px; float:right;">
<div style="height:60px; font-size:14px;">
<div style="height:60px;">
<div style="width:300px;height:60px;float:left; margin-right:20px;">
<ul class="ul_menu">
<li><a href="reg.html">用户注册</a></li>
<li><a href="help.html">帮助中心</a></li>
</ul>
</div>
<div style="width:230px;float:right;height:60px; line-height:60px; margin-right:10px;font-size:16px;">
<img src="images/400tel.png" />
</div>
</div>
</div>
<div style="height:50px;margin-top:15px;">
<div style="float:left;background:rgb(255, 152, 0);width:100px;height:50px; line-height:50px; text-align:center; color:#fff; font-size:18px;font-family:'微软雅黑';">平台登录</div>
<div style="width:18px;height:50px;float:left; background:url(images/login_jian.png);"></div>
<form action="" id="myLoginForm" method="post">
<div class="login-item">
<input name="username" type="text" class="username" placeholder='帐号' autocomplete="off" />
<input name="password" type="text" class="password" placeholder='密码' autocomplete="off" />
<button class="btn-submit" type="submit" data-loading="登录中" >登 录</button>
</div>
<input type="hidden" name="_eventId" value="submit" />
<input type="hidden" name="lt" id="lt" value="">
</form>
</body>
</html>
cas sever增加两个类:
package com.denger.sso.util;
public class CasUtility {
/**
* Removes the previously attached GET parameters "lt" and "error_message"
* to be able to send new ones.
*
* @param casUrl
* @return
*/
public static String resetUrl(String casUrl) {
String cleanedUrl;
String[] paramsToBeRemoved = new String[] { "lt", "error_message", "get-lt" };
cleanedUrl = removeHttpGetParameters(casUrl, paramsToBeRemoved);
return cleanedUrl;
}
/**
* Removes selected HTTP GET parameters from a given URL
*
* @param casUrl
* @param paramsToBeRemoved
* @return
*/
public static String removeHttpGetParameters(String casUrl,
String[] paramsToBeRemoved) {
String cleanedUrl = casUrl;
if (casUrl != null) {
// check if there is any query string at all
if (casUrl.indexOf("?") == -1) {
return casUrl;
} else {
// determine the start and end position of the parameters to be
// removed
int startPosition, endPosition;
boolean containsOneOfTheUnwantedParams = false;
for (String paramToBeErased : paramsToBeRemoved) {
startPosition = -1;
endPosition = -1;
if (cleanedUrl.indexOf("?" + paramToBeErased + "=") > -1) {
startPosition = cleanedUrl.indexOf("?"
+ paramToBeErased + "=") + 1;
} else if (cleanedUrl.indexOf("&" + paramToBeErased + "=") > -1) {
startPosition = cleanedUrl.indexOf("&"
+ paramToBeErased + "=") + 1;
}
if (startPosition > -1) {
int temp = cleanedUrl.indexOf("&", startPosition);
endPosition = (temp > -1) ? temp + 1 : cleanedUrl
.length();
// remove that parameter, leaving the rest untouched
cleanedUrl = cleanedUrl.substring(0, startPosition)
+ cleanedUrl.substring(endPosition);
containsOneOfTheUnwantedParams = true;
}
}
// wenn nur noch das Fragezeichen vom query string 鈭毬篵rig oder am
// schluss ein "&", dann auch dieses entfernen
if (cleanedUrl.endsWith("?") || cleanedUrl.endsWith("&")) {
cleanedUrl = cleanedUrl.substring(0,
cleanedUrl.length() - 1);
}
// parameter mehrfach angegeben wurde...
if (!containsOneOfTheUnwantedParams)
return casUrl;
else
cleanedUrl = removeHttpGetParameters(cleanedUrl,
paramsToBeRemoved);
}
}
return cleanedUrl;
}
}
package com.denger.sso.web;
import javax.servlet.http.HttpServletRequest;
import org.jasig.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
public class ProvideLoginTicketAction extends AbstractAction{
@Override
protected Event doExecute(RequestContext context) throws Exception {
final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) {
return result("loginTicketRequested");
}
return result("continue");
}
}
修改源码org.jasig.cas.web.flow.AuthenticationViaFormAction 中的submit方法:
try {
WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
putWarnCookieIfRequestParameterPresent(context);
return "success";
} catch (final TicketException e) {
populateErrorsInstance(e, messageContext);
// 当验证失败后,判断参数中是否获否 login-at 参数,如果包含的话则跳转至 login ticket 获取页
String referer = context.getRequestParameters().get("login-at");
if (!org.apache.commons.lang.StringUtils.isBlank(referer)) {
return "errorForRemoteRequestor";
}
return "error";
}
修改cas-servelt增加以下代码:
<bean id="provideLoginTicketAction" class="com.denger.sso.web.ProvideLoginTicketAction"/>
修改deployerConfigContext.xml,换成我自己写的数据库验证:
注释掉 <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
换成:<bean class="com.authentication.umc.CasDaoAuthenticationHandler"/> (并将自己写的验证authentication.jar包放入lib中)
修改login-webflow.xml,在initialFlowSetupAction下面增加如下代码:
<action-state id="provideLoginTicket">
<evaluate expression="provideLoginTicketAction"/>
<transition on="loginTicketRequested" to ="viewRedirectToRequestor" />
<transition on="continue" to="ticketGrantingTicketExistsCheck" />
</action-state>
<view-state id="viewRedirectToRequestor" view="casRedirectToRequestorView" model="credentials">
<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
<binder>
<binding property="username" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<set name="flowScope.credentials" value="credentials" />
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
再建一个数据库配置文件extend.properties:
#=====DATABASE SETTING=======
mysql-driver=com.mysql.jdbc.Driver
mysql-url=jdbc:mysql://127.0.0.1:3306/portal
mysql-user=root
mysql-password=123456
最后在view\jsp\default\ui 下增加获取lt 的 viewRedirectToRequestor.jsp页面:
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="com.denger.sso.util.CasUtility"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%
String separator = "";
// 需要输入 login-at 参数,当生成lt后或登录失败后则重新跳转至 原登录页,并传入参数 lt 和 error_message
String referer = request.getParameter("login-at");
referer = CasUtility.resetUrl(referer);
if (referer != null && referer.length() > 0) {
separator = (referer.indexOf("?") > -1) ? "&" : "?";
%>
<html>
<title>cas get login ticket</title>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
var redirectURL = "<%=referer + separator%>lt=${flowExecutionKey}";
<spring:hasBindErrors name="credentials">
var errorMsg = '<c:forEach var="error" items="${errors.allErrors}"><spring:message code="${error.code}" text="${error.defaultMessage}" /></c:forEach>';
redirectURL += '&error_message=' + encodeURIComponent (errorMsg);
</spring:hasBindErrors>
window.location.href = redirectURL;
</script>
</head>
<body></body>
</html>
<%
} else {
%>
<script>window.location.href = "/cas/login";</script>
<%
}
%>