现在的位置: 首页 > 综合 > 正文

SSO(三) cas自定义登录页面

2014年02月06日 ⁄ 综合 ⁄ 共 5303字 ⁄ 字号 评论关闭

有时候各个应用希望有独立风格的登录页面,而不是cas提供的统一登录页面,网上现在有几种方式:iframe, javascript。本文参考了https://wiki.jasig.org/display/CAS/Using+CAS+without+the+Login+Screen, 并在其基础上实现了登录出错重定向至自定义登录页面。

由于cas登录首先要获取lt与execution这两个参数,因此,主要实现方案就是通过在自定义登录页面加入标志位,提交到cas的登录页面casLoginView.jsp,这个页面会根据标志位进行二次提交。如果用户名密码失败还要求能够返回到原登录页面并给出提示,主要实现方式是改变cas的web flow,在提交的时候判断是否是自定义页面登录,是的话进入一个新的状态,这个状态完成页面跳转,并回传错误信息。

自定义登录页面:

<html>
<head>
</head>
<body>
	<script type="text/javascript">
        function getQueryStringByName(name) {
             var result = location.search.match(new RegExp("[\?\&]" + name+ "=([^\&]+)","i"));
             if(result == null || result.length < 1){
             return "";
         }
         return result[1];
         }
        var info = getQueryStringByName('info');
	if (info == "error")
	    alert("用户名密码错误!");
	</script>
    <form method="GET" action="http://127.0.0.1:8080/cas/login">
        <p>Username : <input type="text" name="username" /></p>
        <p>Password : <input type="password" name="password" /></p>
        <p>Remember me : <input type="checkbox" name="rememberMe" value="true" /></p>
        <p><input type="submit" value="Login !" /></p>
		<input type="hidden" name="auto" value="true" />
        <input type="hidden" name="login_from" value="http://127.0.0.1:8080/myApp/login.html" />
        <input type="hidden" name="service" value="http://127.0.0.1:8080/myApp/users.htm" />
    </form>
</body>
</html>

改造的cas-server-webapp工程中的cas登录页:WEB-INF/view/jsp/default/ui/casLoginView.jsp。

<%@ page contentType="text/html; charset=UTF-8" %>
<%
String auto = request.getParameter("auto");
if (auto != null && auto.equals("true")) {
%>
<html>
    <head>
        <script language="javascript">
            function doAutoLogin() {
                document.forms[0].submit();
            }
        </script>
    </head>
    <body onload="doAutoLogin();">
        <form id="credentials" method="POST" action="<%= request.getContextPath() %>/login?service=<%= request.getParameter("service") %>"> 
            <input type="hidden" name="lt" value="${loginTicket}" />
            <input type="hidden" name="execution" value="${flowExecutionKey}" />
            <input type="hidden" name="_eventId" value="submit" />
            <input type="hidden" name="username" value="<%= request.getParameter("username") %>" />
            <input type="hidden" name="password" value="<%= request.getParameter("password") %>" />
            <input type="hidden" name="login_from" value="<%= request.getParameter("login_from") %>" />
            <% if ("true".equals(request.getParameter("rememberMe"))) {%>
                <input type="hidden" name="rememberMe" value="true" />
            <% } %>
             
            <input type="submit" value="Submit" style="visibility: hidden;" />
        </form>
    </body>
</html>
<%
} else {
%>
<jsp:directive.include file="includes/top.jsp" />
......
<jsp:directive.include file="includes/bottom.jsp" />
<%
}
%>

cas-server-core工程的AuthenticationViaFormAction.java需要改造:

在submit函数中,改造如下:

try {
            WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
            putWarnCookieIfRequestParameterPresent(context);
            return "success";
        } catch (final TicketException e) {
            String login_from = context.getRequestParameters().get("login_from");
            if (login_from != null && login_from.length() > 0) {
                context.getRequestScope().put("redirectUrl", login_from + "?info=error");
                return "customizedRedirect";
            }
            populateErrorsInstance(e, messageContext);
            if (isCauseAuthenticationException(e)) {
                return getAuthenticationExceptionEventId(e);
            }
            return "error";
        }

其中

String login_from = context.getRequestParameters().get("login_from");
            if (login_from != null && login_from.length() > 0) {
                context.getRequestScope().put("redirectUrl", login_from + "?info=error");
                return "customizedRedirect";
            }

是新加的。

注意,maven编译cas-server-core最好采用-Dmaven.test.skip=true clean package install跳过测试。

然后在cas-server-webapp工程中

修改WEB-INF/login-webflow.xml,

<action-state id="realSubmit">
        <evaluate expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credentials, messageContext)" />
        <!--
          To enable LPPE on the 'warn' replace the below transition with:
          <transition on="warn" to="passwordPolicyCheck" />

          CAS will attempt to transition to the 'warn' when there's a 'renew' parameter
          and there exists a ticketGrantingId and a service for the incoming request.
        -->
        <transition on="warn" to="warn" />
        <!--
          To enable LPPE on the 'success' replace the below transition with:
          <transition on="success" to="passwordPolicyCheck" />
        -->
        <transition on="success" to="sendTicketGrantingTicket" />
        <transition on="error" to="generateLoginTicket" />
        <!--加入该transition , 当验证失败之后转到自定义页面 -->  
        <transition on="customizedRedirect" to="customizedRedirectView" />
        <transition on="accountDisabled" to="casAccountDisabledView" />
        <transition on="mustChangePassword" to="casMustChangePassView" />
        <transition on="accountLocked" to="casAccountLockedView" />
        <transition on="badHours" to="casBadHoursView" />
        <transition on="badWorkstation" to="casBadWorkstationView" />
        <transition on="passwordExpired" to="casExpiredPassView" />
</action-state>

其中

<transition on="customizedRedirect" to="customizedRedirectView" />

是新加的。

另外,还要新加一个状态:

<end-state id="customizedRedirectView" view="externalRedirect:${requestScope.redirectUrl}" />

备注:

cas 源码下载地址http://downloads.jasig.org/cas/  我用的是3.5.2

另外,可以直接用我已经编译好的http://download.csdn.net/detail/sundongsdu/6681187

抱歉!评论已关闭.