zoukankan      html  css  js  c++  java
  • CAS自定义登陆页面

    参考文档:

    http://www.360doc.com/content/14/0719/16/834950_395508432.shtml

    http://blog.sina.com.cn/s/blog_7d491cfb0101fa5o.html

    前两篇都是参考以下两篇文章:

    http://denger.iteye.com/blog/809170

    http://denger.iteye.com/blog/1119233

    一.前言

    cas版本:cas-server-3.5.2-release

    以下我们所做的服务器端代码的修改都是在cas-server-webapp中

    二.问题分析

    获取cas登录时所需要的参数,其中最主要是lt和execution这两个动态生成的参数,因此,实现cas自定义登录的步骤:

    第一步:获取lt/execution的值

    第二步:自定义界面进行登录

    第三步:给出相应的提示信息,并跳转到指定界面

    三.实现过程

    1、修改服务器端代码,包括创建ProvideLoginTicketAction.class,用于处理获得it/execution的值,并修改login-webflow等配置文件等操作

    (1)创建ProvideLoginTicketAction.java

    package org.jasig.cas.util;
    
    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.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);
            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);
                WebUtils.putLoginTicket(context, loginTicket);
                return result("loginTicketRequested");
            }
            return result("continue");
        }
    
    }

    (2)创建AjaxLoginServiceTicketAction.java

    package org.jasig.cas.util;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.lang.BooleanUtils;
    import org.apache.commons.lang.StringUtils;
    import org.jasig.cas.authentication.principal.Service;
    import org.jasig.cas.web.support.WebUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.webflow.action.AbstractAction;
    import org.springframework.webflow.execution.Event;
    import org.springframework.webflow.execution.RequestContext;
    
    public class AjaxLoginServiceTicketAction extends AbstractAction {
        
        private final Logger log = LoggerFactory.getLogger(getClass()); 
        protected static final String J_CALLBACK = "feedBackUrlCallBack";
        @Override
        protected Event doExecute(final RequestContext context) {
            HttpServletRequest request = WebUtils.getHttpServletRequest(context);
            Event event = context.getCurrentEvent();
            boolean isAjax = BooleanUtils.toBoolean(request.getParameter("isajax"));
           
            if (!isAjax){  // 非 ajax/iframe 方式登录,返回当前 event.
             return event;
            }
         boolean isLoginSuccess;
         // Login Successful.
         if ("success".equals(event.getId())){ //是否登录成功
          final Service service = WebUtils.getService(context);
                final String serviceTicket = WebUtils.getServiceTicketFromRequestScope(context);
                if (service != null){  //设置登录成功之后 跳转的地址
                 request.setAttribute("service", service.getId());
                }
                request.setAttribute("ticket", serviceTicket);
                isLoginSuccess = true;
         } else { // Login Fails..
          isLoginSuccess = false;
         }
            boolean isFrame = BooleanUtils.toBoolean(request.getParameter("isframe"));
            String callback = request.getParameter("callback");
            String clientUrl = request.getParameter("login-at");
            if(StringUtils.isEmpty(callback)){ // 如果未转入 callback 参数,则采用默认 callback 函数名
             callback = J_CALLBACK;
            }
            if(isFrame){ // 如果采用了 iframe ,则 concat 其 parent 。
             callback = "parent.".concat(callback);
            }
            request.setAttribute("isFrame", isFrame);
            request.setAttribute("callback", callback);
            request.setAttribute("clientUrl", clientUrl);
            request.setAttribute("isLogin", isLoginSuccess);
            return new Event(this, "ajaxView"); // 转入 ajaxLogin.jsp 页面
        }
    }

    (3)在cas-server.xml中声明ProvideLoginTicketAction和AjaxLoginServiceTicketAction

    <bean id="provideLoginTicketAction" class="org.jasig.cas.util.ProvideLoginTicketAction"
          p:ticketIdGenerator-ref = "loginTicketUniqueIdGenerator"></bean>
      <bean id="ajaxLoginServiceTicketAction" class="org.jasig.cas.util.AjaxLoginServiceTicketAction"/>
      

    (4)修改login-webflow.xml

    <action-state id="generateServiceTicket">
            <evaluate expression="generateServiceTicketAction" />
            <!-- <transition on="success" to ="warn" /> 
            <transition on="error" to="generateLoginTicket" />-->
            <transition on="success" to ="loginResponse" /> 
            <transition on="error" to="loginResponse" />
            <transition on="gateway" to="gatewayServicesManagementCheck" />
        </action-state>
    <action-state id="realSubmit">
      <evaluate
       expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credentials, messageContext)" />
      <transition on="warn" to="warn" />
      <transition on="success" to="sendTicketGrantingTicket" />
      <!--将 to="viewLoginForm" 修改为 to="loginResponse" -->              
      <transition on="error" to="loginResponse" />
     </action-state>

    (5)在login-webflow.xml中添加

    <action-state id="loginResponse">
              <evaluate expression="ajaxLoginServiceTicketAction" />
              <!--非ajax/iframe方式登录,采取原流程处理 -->
              <transition on="success" to="warn" />
              <transition on="error" to="viewLoginForm" />
              <!-- 反之,则进入 viewAjaxLoginView 页面 -->
              <transition on="ajaxView" to="viewAjaxLoginView" />
         </action-state>

    在<on-start></on-start>标签后添加

    <action-state id="provideLoginTicketAction">
                <evaluate expression="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 expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
            </transition>
         </view-state>
    在最后一个<end-state>标签后添加
    <end-state id="viewAjaxLoginView" view="viewAjaxLoginView" />

    (6)创建ProvideLoginTicketAction执行后要跳转的responseLoginTicketInfo.jsp

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
        pageEncoding="ISO-8859-1"%>
    <%
    response.addHeader("Content-Type", "application/x-javascript");
    out.print("flightHandler({'lt':'");%>${loginTicket}<%out.print("','execution':'");%>${flowExecutionKey}<%out.print("'});");%>

    (7)创建AjaxLoginServiceTicketAction执行后要跳转的ajaxLogin.jsp

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <script type="text/javascript">
       <%
        Boolean isFrame = (Boolean)request.getAttribute("isFrame");
        Boolean isLogin = (Boolean)request.getAttribute("isLogin");
        // 登录成功
        if(isLogin){
         if(isFrame){%>
          parent.location.replace('${service}?ticket=${ticket}')
         <%} else{%>
          location.replace('${service}?ticket=${ticket}')
         <%}
        }else{
       %>
       parent.location.replace('${clientUrl}?msg=error')
       <%
        }
       %>
      </script>

    (8)在default_views.properties(路径:/cas-server-webapp/src/main/webapp/WEB-INF/classes/default_views.properties)

    中增加responseLoginTicketInfo.jsp和ajaxLogin.jsp的配置

    responseLoginTicketInfoView.(class)=org.springframework.web.servlet.view.JstlView
    responseLoginTicketInfoView.url=/WEB-INF/view/jsp/default/ui/responseLoginTicketInfo.jsp
    
    viewAjaxLoginView.(class)=org.springframework.web.servlet.view.JstlView
    viewAjaxLoginView.url=/WEB-INF/view/jsp/default/ui/ajaxLogin.jsp

    2、创建客户端代码

    (1)客户端登录界面index.aspx

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="login" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Client demo</title> 
    </head>
    <body>
        <div></div>
        <form action="" method="post" onsubmit="return loginValidate();" target="ssoLoginFrame" id="loginFrm">
          <div class="red" style="height:12px;color:red" id="login_msg"></div>
            <ul>
           
           <li>
            <em>用户名:</em>
            <input name="username" id="username" type="text" class="required" style=" 180px" size="25"/>
           </li>
           <li>
            <em>密码:</em>
            <input name="password" type="password"  id="password" class="required" style=" 180px" size="25"/>
           </li>
           <li class="mai">
            <em>&nbsp;</em>
            <input type="checkbox" name="rememberMe" id="rememberMe" value="true"/>
            &nbsp;自动登录
            <a href="/retrieve">忘记密码?</a>
           </li>
           <li>
            <em>&nbsp;</em>
            <input type="hidden" name="isajax" value="true" />
            <input type="hidden" name="isframe" value="true" />
            <input type="hidden" name="lt" value="" id="cas_loginTicket"/>
            <input type="hidden" name="execution" value="" id="cas_execution"/>
            <input type="hidden" name="_eventId" value="submit"/>
            <input class="btn-submit" name="submit" accesskey="l" value="登录" tabindex="4" type="submit"/>
            <input class="btn-reset" name="reset" accesskey="c" value="重置" tabindex="5" type="reset"/>
            <input type="hidden" name="login-at" value ="" id="login_at"/>
           </li>
          </ul>
         </form>  
    </body>
        <script type = "text/javascript" src="js/jquery-1.9.1.min.js"></script>
        <script type = "text/javascript" src="js/index.js"></script>
        <iframe style="display:none;0;height:0" id="ssoLoginFrame" name="ssoLoginFrame" src="javascript:false;"></iframe>
    </html>

    (2)对应的js代码index.js

    var urlData;
    $(function () {
        initData();
        var login_error_msg = GetQueryString("msg");
        if (login_error_msg != null && login_error_msg.toString().length > 1) {
            $("#login_msg").text("用户名或密码错误");
        }
       // $("#login_msg").text(login_error_msg.toString());
    });
    
    var flushLoginTicket = function () {
        var _service = 'service=' + encodeURIComponent(urlData._service);
        var urlOfGetLt = urlData.serverUrl + '?' + _service + '&get-lt=true&n=' + new Date().getTime();
        $.ajax({
            type: 'get',
            async: false,
            url: urlOfGetLt,
            dataType: 'jsonp',
            jsonp: 'callback',
            jsonpCallback: 'flightHandler',
            success: function (data) {
                $("#cas_loginTicket").val(data.lt);
                $("#cas_execution").val(data.execution);
            },
            error: function () {
                console.log("ERROR")
            }
        });
    }
    
    var loginValidate = function () {
        var msg;
        if ($.trim($('#username').val()).length == 0) {
            msg = "用户名不能为空。";
        } else if ($.trim($('#password').val()).length == 0) {
            msg = "密码不能为空。";
        }
        if (msg && msg.length > 0) {
            $('#login_msg').fadeOut().text(msg).fadeIn();
            return false;
            // Can't request the login ticket.
        } else if ($('#cas_loginTicket').val().length == 0) {
            $('#login_msg').text('服务器正忙,请稍后再试..');
            return false;
        } else {
            return true;
        }
    }
    
    function GetQueryString(name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) return unescape(r[2]); return null;
    }
    
    function initData() {
        $.get('conf/url.json').done(function (data) {
            urlData = eval('(' + data + ')');
            $("#loginFrm")[0].setAttribute("action", urlData.serverUrl);
            $("#login_at").val(urlData.clientUrl);
            flushLoginTicket();
        });
    }

    (3)对应的json数据url.json,用于存储服务器url和客户端url

    /*
        _service:成功后跳转的路径
        serverUrl:要连接的服务器路径
        clientUrl:登录失败后跳转的路径
    */
    {
        "_service": "http://localhost:54872/demoweb/home.aspx",
        "serverUrl": "https://localhost:8443/cas/login",
        "clientUrl": "http://localhost:54872/demoweb/index.aspx"
    }

    以上只是将整个修改过程提炼出来,并没有解释详细原因,具体细节可参考上面的几篇文章。

  • 相关阅读:
    java代码如何快速添加作者描述的注释最好能有详细的图解
    实现ModelDriver接口的功能
    Java Class类以及获取Class实例的三种方式
    java中的clone()
    applicationContext.xml 配置文件的存放位置
    Spring 整合hibernante 错误java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    Struts2配置问题java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    第三篇:解析库之re、beautifulsoup、pyquery(转)
    第二篇:请求库之requests,selenium
    爬虫基本原理(转)
  • 原文地址:https://www.cnblogs.com/hzwl-2015/p/4613185.html
Copyright © 2011-2022 走看看