验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤

废话就不多说了,开始。。。

    

如果csdn看着不舒服,请移步http://hi.baidu.com/ae6623/item/34f6e23bb424b8342e0f819f,和本系列教程篇同步更新。

    


    

环境:

    

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)

    


    

之前做的界面里面缺少一个验证码的功能,上周由于弄其他事情去了,就没有开始验证码的教程写作,今天补上,希望能按照教程制作出你们想要的功能。

    


    

结果图:

    


    

验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤_第1张图片

    

验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤_第2张图片

    

验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤_第3张图片

    


    

至此为止,五篇教程,自定义的java类不是很多,还不是很深刻。包结构和jar包如下图,程序去我的csdn下载频道下载。

    

验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤_第4张图片

    


    

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>

    
验证码类[置顶] SSO单点登录系列5:cas单点登录增加验证码功能完整步骤_第5张图片

    


    

    

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

    


    

 

    csdn博客:落雨 :http://blog.csdn.net/ae6623

    百度博客:落雨 :http://hi.baidu.com/ae6623/item/34f6e23bb424b8342e0f819f

                               http://hi.baidu.com/ae6623

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

文章结束给大家分享下程序员的一些笑话语录: 问:你觉得让你女朋友(或者任何一个女的)从你和李彦宏之间选一个,你觉得她会选谁?  
  答:因为李艳红这种败类,所以我没女友!

你可能感兴趣的:(单点登录)