一、说明 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标签之后添加普通浏览复制代码 <action-state id= "provideLoginTicket"> < evaluate = "provideLoginTicketAction"/> <transition on= "loginTicketRequested" to = "viewResponseLoginTicketInfo" /> <transition on= "continue" to= "ticketGrantingTicketExistsCheck" /> </action-state> <view-state id= "viewResponseLoginTicketInfo" view= "responseLoginTicketInfoView" model= "credentials"> <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"> < evaluate = "authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /> </transition> </view-state>
(2)在cas-servlet.xml中声明provideLoginTicketAction
- <bean id="provideLoginTicketAction" class="net.water.cas.controller.ProvideLoginTicketAction"
- p:ticketIdGenerator-ref="loginTicketUniqueIdGenerator" />
复制代码 (3)添加ProvideLoginTicketAction.java普通浏览复制代码 package net.water.cas.controller ;import javax.servlet.http.HttpServletRequest ;import javax.validation.constraints.NotNull ;import org.apache.commons.logging.Log ;import org.apache.commons.logging.LogFactory ;import org.jasig.cas.util.UniqueTicketIdGenerator ;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{ private static final String PREFIX = "LT"; private final Log logger = LogFactory.getLog (getClass ()); @NotNull private UniqueTicketIdGenerator ticketIdGenerator ; public final String generate (final RequestContext context ) { final String loginTicket = this.ticketIdGenerator.getNewTicketId (PREFIX ); this.logger.debug ("Generated login ticket " + loginTicket ); WebUtils.putLoginTicket (context, loginTicket ); return "generated"; } public void setTicketIdGenerator (final UniqueTicketIdGenerator generator ) { this.ticketIdGenerator = generator ; } @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")) { final String loginTicket = this.ticketIdGenerator.getNewTicketId (PREFIX ); this.logger.debug ("--------------Generated login ticket :" + loginTicket ); WebUtils.putLoginTicket (context, loginTicket ); return result ("loginTicketRequested"); } return result ("continue"); } }
(4)在default_views.properties中添加页面的配置
- responseLoginTicketInfoView.(class)=org.springframework.web.servlet.view.JstlView
- responseLoginTicketInfoView.url=/WEB-INF/view/jsp/default/ui/responseLoginTicketInfo.jsp
复制代码 (5)添加responseLoginTicketInfo.jsp文件
- <%@ page contentType="text/html; charset=UTF-8"%>
- <%out.print("flightHandler({'lt':'");%>${loginTicket}<%out.print("','execution':'");%>${flowExecutionKey}<%out.print("'});");%>
复制代码 2、客户端登录页面login.jsp
- <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www./TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www./1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>客户端登录cas-demo</title>
- <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.4.2.min.js"></script>
- <script type="text/javascript">
- $(function(){
- flushLoginTicket();
- });
- var flushLoginTicket = function(){
- var _services = 'service=' + encodeURIComponent('http://localhost:8080/security/admin/home.jsp');
- var urlOfGetLt = 'http://localhost:8080/casServer/login?'+_services+'&get-lt=true&n='+new Date().getTime();
- $.ajax({
- type: "get",
- async: false,
- url: urlOfGetLt,
- dataType: "jsonp",
- jsonp: "callback",
- jsonpCallback:"flightHandler",
- success: function(json){
- //alert('lt: ' + json.lt + ',execution: ' + json.execution);
- $("#cas_loginTicket").val(json.lt);
- $("#cas_execution").val(json.execution);
- },
- error: function(){
- alert("无法获取登录key");
- }
- });
- };
- <blockquote> var loginValidate = function(){
复制代码 至此,当用户名/密码输入正确时,已经可以正常跳转到指定的页面,但错误的话还是会到casServer默认的登录页面。 3、登录失败时在客户端提示 (1)修改org.jasig.cas.web.flow.AuthenticationViaFormAction.java的submit方法
- try {
- WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
- putWarnCookieIfRequestParameterPresent(context);
- return "success";
- } catch (final TicketException e) {
- populateErrorsInstance(e, messageContext);
- //客户端登录错误提示
- String referer = context.getRequestParameters().get("login-at");
- if(referer!=null && !"".equals(referer)){
- return "errorForRemoteRequestor";
- }
- if (isCauseAuthenticationException(e))
- return getAuthenticationExceptionEventId(e);
- return "error";
- }
复制代码 (2)修改login-webflow.xml 在realSubmit的声明中添加
- <transition on="errorForRemoteRequestor" to="viewRedirectToRequestorView" />
复制代码 添加viewRedirectToRequestorView的声明
- <end-state id="viewRedirectToRequestorView" view="viewRedirectToRequestorView" />
复制代码 (3)在default_views.properties中添加页面的配置
- viewRedirectToRequestorView.(class)=org.springframework.web.servlet.view.JstlView
- viewRedirectToRequestorView.url=/WEB-INF/view/jsp/default/ui/redirectToRequestor.jsp
复制代码 (4)添加redirectToRequestor.jsp页面
- <%@ page contentType="text/html; charset=UTF-8"%>
- <%
- String referer = request.getParameter("login-at");
- String separator = (referer.indexOf("?") > -1) ? "&" : "?";
- %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www./TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www./1999/xhtml" >
- <head>
- <script type="text/javascript" language="javascript">
- <!--
- var redirectURL = "<%=referer%>" + "<%=separator%>" + "login_error_msg=" + encodeURIComponent("用户名或密码错误");
- window.location.replace(redirectURL);
- -->
- </script>
- <title>Redirect</title>
- </head>
- <body></body>
- </html>
复制代码 (5)客户端登录页面login.jsp添加错误提示 script中添加动态显示
- $(function(){
- if("${param['login_error_msg']}" != ""){
- $("#div_login_msg").html("${param['login_error_msg']}");
- }
- });
复制代码 页面中添加一个div
- <div id="div_login_msg"></div>
复制代码 form中添加login-at参数
- <input type="hidden" name="login-at" value="http://localhost:8080/security/login.jsp" />
复制代码 以上
|