1. 程式人生 > >SSO單點登入系列5:cas單點登入增加驗證碼功能完整步驟

SSO單點登入系列5:cas單點登入增加驗證碼功能完整步驟

本篇教程cas-server端下載地址:解壓後,直接放到tomcat的webapp目錄下就能用了,不過你需要登入的話,要修改資料來源,C:\tomcat7\webapps\casServer\WEB-INF\deployerConfigContext.xml,嗯。地址:http://pan.baidu.com/share/link?shareid=439449164&uk=436295647

落雨 cas 單點登入

環境:

server端:cas-server-core-3.5.2.jar、cas-client-core-3.2.1.jar

client端:cas-client-core-3.1.3.jar、http遮蔽了https後的casclient.jar(http://blog.csdn.net/dengtaowei/article/details/7039399)

之前做的介面裡面缺少一個驗證碼的功能,上週由於搞其他事情去了,就沒有開始驗證碼的教程寫作,今天補上,希望能按照教程製作出你們想要的功能。

結果圖:




至此為止,五篇教程,自定義的java類不是很多,還不是很深入。包結構和jar包如下圖,程式去我的csdn下載頻道下載。


C:\TOMCAT7\WEBAPPS\CASSERVER\WEB-INF\CLASSES\ORG
└─jasig
    └─cas
        ├─authentication
        │  └─handler
        │      │  CaptchaImageLoginCredentials.class
        │      │  Crypt.class
        │      │  ImageVaditeAuthenticationViaFormAction.class
        │      │  MD5.class
        │      │  RsCasDaoAuthenticationHandler.class
        │      │  
        │      ├─captchaImage
        │      │      CaptchaImageCreateController.class
        │      │      
        │      └─util
        │              ValidatorCodeUtil$ValidatorCode.class
        │              ValidatorCodeUtil.class
        │              
        ├─util
        │      AutowiringSchedulerFactoryBean.class
        │      
        └─web
            │  FlowExecutionExceptionResolver.class
            │  
            └─flow
                    GatewayServicesManagementCheck.class
                    ServiceAuthorizationCheck.class
                    

1.cas-servlet.xml 

.找到C:\tomcat7\webapps\casServer\WEB-INF\cas-servlet.xml檔案,在

bean  id="handlerMappingC" 節點下增加驗證碼請求處理<prop key="/captcha.htm">captchaImageCreateController</prop>
<bean
      id="handlerMappingC"
      class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
      <props>
        <prop key="/logout">logoutController</prop>
        <prop key="/serviceValidate">serviceValidateController</prop>
        <prop key="/validate">legacyValidateController</prop>
        <prop key="/proxy">proxyController</prop>
        <prop key="/proxyValidate">proxyValidateController</prop>
        <prop key="/samlValidate">samlValidateController</prop>
        <prop key="/services/add.html">addRegisteredServiceSimpleFormController</prop>
        <prop key="/services/edit.html">editRegisteredServiceSimpleFormController</prop>
        <prop key="/services/loggedOut.html">serviceLogoutViewController</prop>
        <prop key="/services/viewStatistics.html">viewStatisticsController</prop>
        <prop key="/services/*">manageRegisteredServicesMultiActionController</prop>
        <prop key="/openid/*">openIdProviderController</prop>
        <prop key="/authorizationFailure.html">passThroughController</prop>
        <prop key="/403.html">passThroughController</prop>
        <prop key="/status">healthCheckController</prop>
      <!--增加驗證碼的功能-->
      <prop key="/captcha.htm">captchaImageCreateController</prop>
                                                           
      </props>
    </property>
    <property
        name="alwaysUseFullPath" value="true"/>
    <!--
     uncomment this to enable sending PageRequest events.
     <property
       name="interceptors">
       <list>
         <ref bean="pageRequestHandlerInterceptorAdapter" />
       </list>
     </property>
      -->
  </bean>

captchaImageCreateController需要我們自己寫java類

在上述xml程式碼後面繼續新增一個bean,如下,而類class路徑是我們自己寫的,在myeclipse裡面自己diy的包名org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController

<!--增加一個bean處理驗證碼-->
<bean id="captchaImageCreateController"  class="org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController"></bean>


2.然後我們開始寫這個CaptchaImageCreateController

org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController

CaptchaImageCreateController.java

/**
 * Project Name:casServerHandler
 * File Name:CaptchaImageCreateController.java
 * Package Name:org.jasig.cas.authentication.handler.captchaImage
 * Date:2013-4-28下午03:04:06
 * Copyright (c) 2013, riambsoft All Rights Reserved.
 *
 */
                                                  
package org.jasig.cas.authentication.handler.captchaImage;
import java.io.IOException;
                                                  
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
                                                  
import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil;
import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil.ValidatorCode;
                                                  
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
                                                  
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
// import com.wokejia.flow.ValidatorCodeUtil.ValidatorCode;
                                                  
public class CaptchaImageCreateController implements Controller, InitializingBean {
                                                      
    public void afterPropertiesSet() throws Exception {
                                                          
    }
                                                  
    public ModelAndView handleRequest(HttpServletRequest arg0,
            HttpServletResponse response) throws Exception {
        ValidatorCode codeUtil = ValidatorCodeUtil.getCode();
        System.out.println("code="+codeUtil.getCode());
                                                          
        arg0.getSession().setAttribute("code", codeUtil.getCode());
        // 禁止影象快取。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
                                                  
        ServletOutputStream sos = null;
        try {
            // 將影象輸出到Servlet輸出流中。
            sos = response.getOutputStream();
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);
            encoder.encode(codeUtil.getImage()); 
            sos.flush();
            sos.close();
        } catch (Exception e) {
        } finally {
            if (null != sos) {
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}


3.開始搞驗證碼圖片生成java類的編寫:

這個類中用到了網上經常用的驗證碼生成類,這個類你可以自己隨便寫,下面提供一個網上寫的,生成的驗證碼挺漂亮的。

import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil;

import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil.ValidatorCode;

ValidatorCode類是ValidatorCodeUtil類的一個內部類,程式碼如下

ValidatorCode.java

/**
 * Project Name:casServerHandler
 * File Name:ValidatorCodeUtil.java
 * Package Name:org.jasig.cas.authentication.handler.util
 * Date:2013-4-28下午03:01:38
 * Copyright (c) 2013, riambsoft All Rights Reserved.
 *
 */
                                                 
package org.jasig.cas.authentication.handler.util;
                                                 
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
 * ClassName:ValidatorCodeUtil <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午03:01:38 <br/>
 * 
 * @author Administrator
 * @version
 * @since JDK 1.5
 * @see
 */
public class ValidatorCodeUtil {
    public static ValidatorCode getCode() {
        // 驗證碼圖片的寬度。
        int width = 80;
        // 驗證碼圖片的高度。
        int height = 30;
        BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffImg.createGraphics();
                                                 
        // 建立一個隨機數生成器類。
        Random random = new Random();
                                                 
        // 設定影象背景色(因為是做背景,所以偏淡)
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);
        // 建立字型,字型的大小應該根據圖片的高度來定。
        Font font = new Font("微軟雅黑", Font.HANGING_BASELINE, 28);
        // 設定字型。
        g.setFont(font);
                                                 
        // 畫邊框。
        g.setColor(Color.BLACK);
        g.drawRect(0, 0, width - 1, height - 1);
        // 隨機產生155條幹擾線,使圖象中的認證碼不易被其它程式探測到。
        // g.setColor(Color.GRAY);
        // g.setColor(getRandColor(160, 200));
        // for (int i = 0; i < 155; i++) {
        // int x = random.nextInt(width);
        // int y = random.nextInt(height);
        // int xl = random.nextInt(12);
        // int yl = random.nextInt(12);
        // g.drawLine(x, y, x + xl, y + yl);
        // }
                                                 
        // randomCode用於儲存隨機產生的驗證碼,以便使用者登入後進行驗證。
        StringBuffer randomCode = new StringBuffer();
                                                 
        // 設定預設生成4個驗證碼
        int length = 4;
        // 設定備選驗證碼:包括"a-z"和數字"0-9"
        String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                                                 
        int size = base.length();
                                                 
        // 隨機產生4位數字的驗證碼。
        for (int i = 0; i < length; i++) {
            // 得到隨機產生的驗證碼數字。
            int start = random.nextInt(size);
            String strRand = base.substring(start, start + 1);
                                                           
            // 用隨機產生的顏色將驗證碼繪製到影象中。
            // 生成隨機顏色(因為是做前景,所以偏深)
            // g.setColor(getRandColor(1, 100));
                                                             
            // 呼叫函數出來的顏色相同,可能是因為種子太接近,所以只能直接生成
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(strRand, 15 * i + 6, 24);
                                                 
            // 將產生的四個隨機數組合在一起。
            randomCode.append(strRand);
        }
                                                 
        // 圖象生效
        g.dispose();
        ValidatorCode code = new ValidatorCode();
        code.image = buffImg;
        code.code = randomCode.toString();
        return code;
    }
                                                 
    // 給定範圍獲得隨機顏色
    static Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }
                                                 
    /**
     * 
     * <p class="detail">
     * 驗證碼圖片封裝
     * </p>
     * 
     * @ClassName: ValidatorCode
     * @version V1.0
     * @date 2012-4-9 下午07:24:14
     * @author 羅偉俊
     * 
     */
    public static class ValidatorCode {
        private BufferedImage image;
        private String code;
                                                 
        /**
         * <p class="detail">
         * 圖片流
         * </p>
         * 
         * @return
         */
        public BufferedImage getImage() {
            return image;
        }
                                                 
        /**
         * <p class="detail">
         * 驗證碼
         * </p>
         * 
         * @return
         */
        public String getCode() {
            return code;
        }
    }
}

4.驗證碼生成做完了,那麼我們開始修改預設的認證器的認證方式,增加驗證碼驗證

自己新建一個java類:

ImageVaditeAuthenticationViaFormAction.java,此類其實是改造的org.jasig.cas.web.flow.AuthenticationViaFormAction.java這個類,它裡面本來只是驗證使用者名稱和密碼,我們增加一個成員變數,code,然後在驗證使用者名稱和密碼之前,我們先開始驗證驗證碼。

/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.cas.authentication.handler;
                                     
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
                                     
import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.Credentials;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.ticket.TicketException;
import org.jasig.cas.web.bind.CredentialsBinder;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.util.StringUtils;
import org.springframework.web.util.CookieGenerator;
import org.springframework.webflow.execution.RequestContext;
                                     
/**
 * Action to authenticate credentials and retrieve a TicketGrantingTicket for those credentials. If there is a request for renew, then it also generates the Service Ticket required.
 * 
 * @author Scott Battaglia
 * @version $Revision$ $Date$
 * @since 3.0.4
 */
public class ImageVaditeAuthenticationViaFormAction {
                                     
    // 驗證碼引數:
    private String code = "code";
                                     
    /**
     * Binder that allows additional binding of form object beyond Spring defaults.
     */
    private CredentialsBinder credentialsBinder;
                                     
    /** Core we delegate to for handling all ticket related tasks. */
    @NotNull
    private CentralAuthenticationService centralAuthenticationService;
                                     
    @NotNull
    private CookieGenerator warnCookieGenerator;
                                     
    protected Logger logger = LoggerFactory.getLogger(getClass());
                                     
    public final void doBind(final RequestContext context, final Credentials credentials) throws Exception {
        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
                                     
        if (this.credentialsBinder != null && this.credentialsBinder.supports(credentials.getClass())) {
            this.credentialsBinder.bind(request, credentials);
        }
    }
                                     
    public final String submit(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception {
                                     
        // 檢測驗證碼
        if (credentials instanceof CaptchaImageLoginCredentials) {
            // 這個類也是我們自己搞的,裡面能取到驗證碼
            CaptchaImageLoginCredentials rmupc = (CaptchaImageLoginCredentials) credentials;
            // 從session中取出生成驗證碼的時候就儲存在session中的驗證碼
            String sessionCode = (String) WebUtils.getHttpServletRequest(context).getSession().getAttribute(code);
                                     
            // 如果驗證碼為null
            if (rmupc.getCode() == null) {
                // 寫入日誌
                logger.warn("驗證碼為空");
                // 錯誤資訊,會在配置檔案(messages_zh_CN.properties)裡面先定義好
                final String code = "login.code.tip";
                // 傳送錯誤資訊到前臺
                messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
                return "error";
            }
            // 如果驗證碼不正確
            if (!rmupc.getCode().toUpperCase().equals(sessionCode.toUpperCase())) {
                logger.warn("驗證碼檢驗有誤");
                final String code = "login.code.error";
                messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
                return "error";
            }
                                     
        }
                                     
        // Validate login ticket
        final String authoritativeLoginTicket = WebUtils.getLoginTicketFromFlowScope(context);
        final String providedLoginTicket = WebUtils.getLoginTicketFromRequest(context);
        if (!authoritativeLoginTicket.equals(providedLoginTicket)) {
            this.logger.warn("Invalid login ticket " + providedLoginTicket);
            final String code = "INVALID_TICKET";
            messageContext.addMessage(new MessageBuilder().error().code(code).arg(providedLoginTicket).defaultText(code).build());
            return "error";
        }
                                     
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        final Service service = WebUtils.getService(context);
        if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) {
                                     
            try {
                final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);
                WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
                putWarnCookieIfRequestParameterPresent(context);
                return "warn";
            } catch (final TicketException e) {
                if (isCauseAuthenticationException(e)) {
                    populateErrorsInstance(e, messageContext);
                    return getAuthenticationExceptionEventId(e);
                }
                                     
                this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
                if (logger.isDebugEnabled()) {
                    logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);
                }
            }
        }
                                     
        try {
            WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
            putWarnCookieIfRequestParameterPresent(context);
            return "success";
        } catch (final TicketException e) {
            populateErrorsInstance(e, messageContext);
            if (isCauseAuthenticationException(e))
                return getAuthenticationExceptionEventId(e);
            return "error";
        }
    }
                                     
    private void populateErrorsInstance(final TicketException e, final MessageContext messageContext) {
                                     
        try {
            messageContext.addMessage(new MessageBuilder().error().code(e.getCode()).defaultText(e.getCode()).build());
        } catch (final Exception fe) {
            logger.error(fe.getMessage(), fe);
        }
    }
                                     
    private void putWarnCookieIfRequestParameterPresent(final RequestContext context) {
        final HttpServletResponse response = WebUtils.getHttpServletResponse(context);
                                     
        if (StringUtils.hasText(context.getExternalContext().getRequestParameterMap().get("warn"))) {
            this.warnCookieGenerator.addCookie(response, "true");
        } else {
            this.warnCookieGenerator.removeCookie(response);
        }
    }
                                     
    private AuthenticationException getAuthenticationExceptionAsCause(final TicketException e) {
        return (AuthenticationException) e.getCause();
    }
                                     
    private String getAuthenticationExceptionEventId(final TicketException e) {
        final AuthenticationException authEx = getAuthenticationExceptionAsCause(e);
                                     
        if (this.logger.isDebugEnabled())
            this.logger.debug("An authentication error has occurred. Returning the event id " + authEx.getType());
                                     
        return authEx.getType();
    }
                                     
    private boolean isCauseAuthenticationException(final TicketException e) {
        return e.getCause() != null && AuthenticationException.class.isAssignableFrom(e.getCause().getClass());
    }
                                     
    public final void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {
        this.centralAuthenticationService = centralAuthenticationService;
    }
                                     
    /**
     * Set a CredentialsBinder for additional binding of the HttpServletRequest to the Credentials instance, beyond our default binding of the Credentials as a Form Object in Spring WebMVC parlance. By the time we invoke this CredentialsBinder, we have already engaged in default binding such that for each HttpServletRequest parameter, if there was a JavaBean property of the Credentials implementation of the same name, we have set that property to be the value of the corresponding request parameter. This CredentialsBinder plugin point exists to allow consideration of things other than HttpServletRequest parameters in populating the Credentials (or more sophisticated consideration of the HttpServletRequest parameters).
     * 
     * @param credentialsBinder
     *            the credentials binder to set.
     */
    public final void setCredentialsBinder(final CredentialsBinder credentialsBinder) {
        this.credentialsBinder = credentialsBinder;
    }
                                     
    public final void setWarnCookieGenerator(final CookieGenerator warnCookieGenerator) {
        this.warnCookieGenerator = warnCookieGenerator;
    }
}


ImageVaditeAuthenticationViaFormAction.java用到了另一個類,也是我們需要改造的類,改造的org.jasig.cas.authentication.principal.UsernamePasswordCredentials.java,你把原始碼拿出來和這個類對比一下就知道只是增加了一個private String code;

CaptchaImageLoginCredentials.java

/**
 * Project Name:casServerHandler
 * File Name:CaptchaImageLoginCredentials.java
 * Package Name:org.jasig.cas.authentication.handler
 * Date:2013-4-28下午06:55:08
 * Copyright (c) 2013, riambsoft All Rights Reserved.
 *
 */
                   
package org.jasig.cas.authentication.handler;
                   
import java.util.Map;
                   
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
                   
import org.jasig.cas.authentication.principal.RememberMeUsernamePasswordCredentials;
                   
/**
 * ClassName:CaptchaImageLoginCredentials <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午06:55:08 <br/>
 * 
 * @author Administrator
 * @version
 * @since JDK 1.5
 * @see
 */
public class CaptchaImageLoginCredentials extends RememberMeUsernamePasswordCredentials {
    private static final long serialVersionUID = 1L;
                   
    private Map<String, Object> param;
                   
    /** The username. */
    @NotNull
    @Size(min = 1, message = "驗證碼為空")
    private String code;
                   
    public String getCode() {
        return code;
    }
                   
    public void setCode(String code) {
        this.code = code;
    }
                   
    public Map<String, Object> getParam() {
        return param;
    }
                   
    public void setParam(Map<String, Object> param) {
        this.param = param;
    }
}


5.下面開始對xml檔案進行修改:

1)還是剛才那個路徑,我們之前修改的xml檔案:C:\tomcat7\webapps\casServer\WEB-INF\cas-servlet.xml

<!-- 修改這個bean,變成我們自己的改造後的類
<bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
      p:centralAuthenticationService-ref="centralAuthenticationService"
      p:warnCookieGenerator-ref="warnCookieGenerator"/>
-->
                   
<bean id="authenticationViaFormAction" class="org.jasig.cas.authentication.handler.ImageVaditeAuthenticationViaFormAction"
      p:centralAuthenticationService-ref="centralAuthenticationService"
      p:warnCookieGenerator-ref="warnCookieGenerator"/>
                   
<!-- over -->


2)C:\tomcat7\webapps\casServer\WEB-INF\login-webflow.xml
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
                  
   <!-- 替換這個 
    <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
    -->
    <var name="credentials" class="org.jasig.cas.authentication.handler.CaptchaImageLoginCredentials" />
                  
    <!-- over -->
                  
  <on-start>
        <evaluate expression="initialFlowSetupAction" />
    </on-start>


找到節點:viewLoginForm

 <!-- 修改這個
    <view-state id="viewLoginForm" view="casLoginView" 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>
-->
           
    <view-state id="viewLoginForm" view="casLoginView" model="credentials">
        <binder>
            <binding property="username" />
            <binding property="password" />
            <binding property="code" />
           
        </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>


其實你看到就是增加一個binding屬性code,方便注入到ImageVaditeAuthenticationViaFormAction這個類裡面。

文章末尾會貼上所有xml檔案,以及原始碼下載地址

3)在C:\tomcat7\webapps\casServer\WEB-INF\classes最下面新增錯誤提示資訊,由於是使用unicode編碼,所以是看不懂的字元

login.code.tip=\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801

login.code.error=\u9A8C\u8BC1\u7801\u8F93\u5165\u6709\u8BEF

其實這兩行的意思如下:

login.code.tip=請輸入驗證碼
login.code.error=驗證碼輸入有誤

4)C:\tomcat7\webapps\casServer\WEB-INF\web.xml下新增對URL的處理

<!-- validate code-->
    <servlet-mapping>
    <servlet-name>cas</servlet-name>
    <url-pattern>/captcha.htm</url-pattern>
  </servlet-mapping>
<!--  over-->


這一步很重要,否則首頁開啟時,根本找不到captacha.htm而不顯示圖片,我做這個的時候,也是搞了好久,才發現web.xml這麼重要的配置忘記寫。

5)現在去找你的前臺頁面C:\tomcat7\webapps\casServer\WEB-INF\view\jsp\default\ui\casLoginView.jsp,給加上驗證碼的文字框和響應事件吧,比如說看不清楚換一張

<!-- 驗證碼 -->
                        <div class="row fl-controls-left">
                        <label for="code" class="fl-label">驗證碼:</label>
                             
                        <script type="text/javascript">
                            function refresh(){
                         fm1.vali.src="";
                         fm1.vali.src="captcha.htm";
                        //img.src='captcha.htm?t='+new Date().getTime()
                        }
                    </script>
                        <input class="required" type="text" tabindex="3"  id="code" size="10"   name="code"  autocomplete="off"  style="float:left;"/>
                             
                        <div style="height:30px;width:150px;text-align:center;margin-left:5px; float:left;vertical-align:middle; display: table-cell;">
                        <a href="javascript:refresh();" onclick="refresh();"  style="width:130px;height:30px;">
                             
                        <span style="display: block;float:left;width:60px;height:25px;float:left;">
                            <img id="vali"  width="60" height="30" src="captcha.htm" style="padding-left: 5px;"/>
                        </span>
                         <span style="display:block;width:60px;height:100%;float:left;vertical-align:middle; display: table-cell;margin-left:15px;">看不清楚?換一個</span>
                        </a>
                             
                        </div>


ok 大功告成,編譯完的class這幾個檔案,統統放入你的server端的各個指定路徑下,重啟tomcat,回帖感謝各位百度前輩吧。

文中所涉及的xml檔案完整版:

由於是先搞完的程式,後寫的文件,所有如有步驟遺漏請及時聯絡本人,定做詳細解答

2013年5月13日10:59:48

落雨

qq:394263788

百度部落格:落雨 :http://hi.baidu.com/ae6623/item/34f6e23bb424b8342e0f819f

                           http://hi.baidu.com/ae6623

​參考帖子:http://my.oschina.net/wjgood/blog/90407