分享

CAS自定义客户端登录界面

 用勿龍潛 2014-07-19
一、说明
CAS-Server端是作为一个独立的项目单独运行的,所有客户端需要登录时,默认是跳转到casServer的统一登录页面。
有很多情况下,客户端也希望有自己的登录界面,这个页面是在客户端项目中的,登录只是这个页面的一部分功能,本文将实现这一效果。
所用casServer版本3.5.0
参考文章
http://denger./blog/809170
http://denger./blog/1119233
二、分析
查看casServer的统一登录页面的from,发现除了username/password两参数外,还有_eventId/service/execution/lt四个,其中_eventId固定值submit,service可以自行设置,lt/execution两项是动态的标识,所以解决方案也就有了,主要分三步:
1、获取lt/execution的值
2、用自定义的form来登录
3、登录出错时的信息提示
三、实现过程
1、修改login-webflow使登录流程在某种特定情况下可以告诉我们lt/execution的值
(1)修改login-webflow.xml,在on-start标签之后添加
普通浏览复制代码
  1.     <action-state id="provideLoginTicket">  
  2.         <evaluate ="provideLoginTicketAction"/>  
  3.         <transition on="loginTicketRequested" to ="viewResponseLoginTicketInfo" />  
  4.         <transition on="continue" to="ticketGrantingTicketExistsCheck" />  
  5.     </action-state>
  6.         <view-state id="viewResponseLoginTicketInfo" view="responseLoginTicketInfoView" model="credentials">
  7.         <binder>  
  8.             <binding property="username" />  
  9.             <binding property="password" />  
  10.         </binder>  
  11.         <on-entry>  
  12.             <set name="viewScope.commandName" value="'credentials'" />  
  13.         </on-entry>  
  14.         <transition on="submit" bind="true" validate="true" to="realSubmit">
  15.             <evaluate ="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />  
  16.         </transition>  
  17.     </view-state>
(2)在cas-servlet.xml中声明provideLoginTicketAction

  1. <bean id="provideLoginTicketAction" class="net.water.cas.controller.ProvideLoginTicketAction"
  2.    p:ticketIdGenerator-ref="loginTicketUniqueIdGenerator" />
复制代码
(3)添加ProvideLoginTicketAction.java
普通浏览复制代码
  1. package net.water.cas.controller;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.validation.constraints.NotNull;
  4. import org.apache.commons.logging.Log;
  5. import org.apache.commons.logging.LogFactory;
  6. import org.jasig.cas.util.UniqueTicketIdGenerator;
  7. import org.jasig.cas.web.support.WebUtils;
  8. import org.springframework.webflow.action.AbstractAction;
  9. import org.springframework.webflow.execution.Event;
  10. import org.springframework.webflow.execution.RequestContext;
  11. public class ProvideLoginTicketAction extends AbstractAction{  
  12.         private static final String PREFIX = "LT";  
  13.         private final Log logger = LogFactory.getLog(getClass());  
  14.         @NotNull  
  15.         private UniqueTicketIdGenerator ticketIdGenerator;  
  16.         public final String generate(final RequestContext context) {  
  17.             final String loginTicket = this.ticketIdGenerator.getNewTicketId(PREFIX);  
  18.             this.logger.debug("Generated login ticket " + loginTicket);  
  19.             WebUtils.putLoginTicket(context, loginTicket);  
  20.             return "generated";  
  21.         }  
  22.         public void setTicketIdGenerator(final UniqueTicketIdGenerator generator) {  
  23.             this.ticketIdGenerator = generator;  
  24.         }  
  25.         @Override  
  26.         protected Event doExecute(RequestContext context) throws Exception {  
  27.             final HttpServletRequest request = WebUtils.getHttpServletRequest(context);  
  28.             if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) {  
  29.                 final String loginTicket = this.ticketIdGenerator.getNewTicketId(PREFIX);  
  30.                 this.logger.debug("--------------Generated login ticket :" + loginTicket);  
  31.                 WebUtils.putLoginTicket(context, loginTicket); 
  32.                 return result("loginTicketRequested");
  33.             }  
  34.             return result("continue");
  35.         }  
  36. }
(4)在default_views.properties中添加页面的配置

  1. responseLoginTicketInfoView.(class)=org.springframework.web.servlet.view.JstlView
  2. responseLoginTicketInfoView.url=/WEB-INF/view/jsp/default/ui/responseLoginTicketInfo.jsp
复制代码
(5)添加responseLoginTicketInfo.jsp文件

  1. <%@ page contentType="text/html; charset=UTF-8"%>
  2. <%out.print("flightHandler({'lt':'");%>${loginTicket}<%out.print("','execution':'");%>${flowExecutionKey}<%out.print("'});");%>
复制代码
2、客户端登录页面login.jsp

  1. <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www./TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www./1999/xhtml">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <title>客户端登录cas-demo</title>
  7. <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.4.2.min.js"></script>
  8. <script type="text/javascript">
  9.                 $(function(){
  10.                         flushLoginTicket();
  11.                 });
  12.                 var flushLoginTicket = function(){
  13.                         var _services = 'service=' + encodeURIComponent('http://localhost:8080/security/admin/home.jsp');
  14.                     var urlOfGetLt = 'http://localhost:8080/casServer/login?'+_services+'&get-lt=true&n='+new Date().getTime();
  15.                     $.ajax({
  16.              type: "get",
  17.              async: false,
  18.              url: urlOfGetLt,
  19.              dataType: "jsonp",
  20.              jsonp: "callback",
  21.              jsonpCallback:"flightHandler",
  22.              success: function(json){
  23.                  //alert('lt: ' + json.lt + ',execution: ' + json.execution);
  24.                  $("#cas_loginTicket").val(json.lt);
  25.                  $("#cas_execution").val(json.execution);
  26.              },
  27.              error: function(){
  28.                  alert("无法获取登录key");
  29.              }
  30.          });
  31.                 };

  32. <blockquote>         var loginValidate = function(){
复制代码
至此,当用户名/密码输入正确时,已经可以正常跳转到指定的页面,但错误的话还是会到casServer默认的登录页面。
3、登录失败时在客户端提示
(1)修改org.jasig.cas.web.flow.AuthenticationViaFormAction.java的submit方法

  1.         try {
  2.             WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
  3.             putWarnCookieIfRequestParameterPresent(context);
  4.             return "success";
  5.         } catch (final TicketException e) {
  6.             populateErrorsInstance(e, messageContext);
  7.             //客户端登录错误提示
  8.             String referer = context.getRequestParameters().get("login-at");
  9.             if(referer!=null && !"".equals(referer)){
  10.                     return "errorForRemoteRequestor";
  11.             }
  12.             if (isCauseAuthenticationException(e))
  13.                 return getAuthenticationExceptionEventId(e);
  14.             return "error";
  15.         }
复制代码
(2)修改login-webflow.xml
在realSubmit的声明中添加

  1. <transition on="errorForRemoteRequestor" to="viewRedirectToRequestorView" />
复制代码
添加viewRedirectToRequestorView的声明

  1. <end-state id="viewRedirectToRequestorView" view="viewRedirectToRequestorView" />
复制代码
(3)在default_views.properties中添加页面的配置

  1. viewRedirectToRequestorView.(class)=org.springframework.web.servlet.view.JstlView
  2. viewRedirectToRequestorView.url=/WEB-INF/view/jsp/default/ui/redirectToRequestor.jsp
复制代码
(4)添加redirectToRequestor.jsp页面

  1. <%@ page contentType="text/html; charset=UTF-8"%>
  2. <%
  3. String referer = request.getParameter("login-at");
  4. String separator = (referer.indexOf("?") > -1) ? "&" : "?";
  5. %>
  6. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www./TR/xhtml1/DTD/xhtml1-transitional.dtd">
  7. <html xmlns="http://www./1999/xhtml" >
  8.   <head>
  9.     <script type="text/javascript" language="javascript">
  10.       <!--
  11.       var redirectURL = "<%=referer%>" + "<%=separator%>" + "login_error_msg=" + encodeURIComponent("用户名或密码错误");
  12.       window.location.replace(redirectURL);
  13.       -->
  14.     </script>
  15.     <title>Redirect</title>
  16.   </head>
  17.   <body></body>
  18. </html>
复制代码
(5)客户端登录页面login.jsp添加错误提示
script中添加动态显示

  1.                 $(function(){
  2.                         if("${param['login_error_msg']}" != ""){
  3.                                 $("#div_login_msg").html("${param['login_error_msg']}");
  4.                         }
  5.                 });
复制代码
页面中添加一个div

  1. <div id="div_login_msg"></div>
复制代码
form中添加login-at参数

  1. <input type="hidden" name="login-at" value="http://localhost:8080/security/login.jsp" />
复制代码
以上

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多