CAS自定义登陆

基于cas3.5.2 sever改造而成。javascript


经过子系统页面登陆:css

<!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"/>html

修改deployerConfigContext.xml,换成我本身写的数据库验证:java

注释掉 <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
换成:<bean class="com.authentication.umc.CasDaoAuthenticationHandler"/> (并将本身写的验证authentication.jar包放入lib中)mysql

修改login-webflow.xml,在initialFlowSetupAction下面增长以下代码:jquery

<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
web


最后在view\jsp\default\ui 下增长获取lt  的 viewRedirectToRequestor.jsp页面:spring

<%@ 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>  
<%         
    }  
%>