本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能用了,不过你需要登录的话,要修改数据源,C:\tomcat7\webapps\casServer\WEB-INF\deployerConfigContext.xml

落雨 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" 节点下增加
  1. <span style="font-family:Microsoft YaHei;font-size:14px;"><bean
  2. id="handlerMappingC"
  3. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  4. <property name="mappings">
  5. <props>
  6. <prop key="/logout">logoutController</prop>
  7. <prop key="/serviceValidate">serviceValidateController</prop>
  8. <prop key="/validate">legacyValidateController</prop>
  9. <prop key="/proxy">proxyController</prop>
  10. <prop key="/proxyValidate">proxyValidateController</prop>
  11. <prop key="/samlValidate">samlValidateController</prop>
  12. <prop key="/services/add.html">addRegisteredServiceSimpleFormController</prop>
  13. <prop key="/services/edit.html">editRegisteredServiceSimpleFormController</prop>
  14. <prop key="/services/loggedOut.html">serviceLogoutViewController</prop>
  15. <prop key="/services/viewStatistics.html">viewStatisticsController</prop>
  16. <prop key="/services/*">manageRegisteredServicesMultiActionController</prop>
  17. <prop key="/openid/*">openIdProviderController</prop>
  18. <prop key="/authorizationFailure.html">passThroughController</prop>
  19. <prop key="/403.html">passThroughController</prop>
  20. <prop key="/status">healthCheckController</prop>
  21. <!--增加验证码的功能-->
  22. <prop key="/captcha.htm">captchaImageCreateController</prop>
  23. </props>
  24. </property>
  25. <property
  26. name="alwaysUseFullPath" value="true"/>
  27. <!--
  28. uncomment this to enable sending PageRequest events.
  29. <property
  30. name="interceptors">
  31. <list>
  32. <ref bean="pageRequestHandlerInterceptorAdapter" />
  33. </list>
  34. </property>
  35. -->
  36. </bean></span>

captchaImageCreateController需要我们自己写java类

在上述xml代码后面继续添加一个bean,如下,而类class路径是我们自己写的,在myeclipse里面自己diy的包名org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController

  1. <span style="font-family:Microsoft YaHei;font-size:14px;"><!--增加一个bean处理验证码-->
  2. <bean id="captchaImageCreateController"  class="org.jasig.cas.authentication.handler.captchaImage.CaptchaImageCreateController"></bean></span>

2.然后我们开始写这个CaptchaImageCreateController类

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

CaptchaImageCreateController.java

  1. /**
  2. * Project Name:casServerHandler
  3. * File Name:CaptchaImageCreateController.java
  4. * Package Name:org.jasig.cas.authentication.handler.captchaImage
  5. * Date:2013-4-28下午03:04:06
  6. * Copyright (c) 2013, riambsoft All Rights Reserved.
  7. *
  8. */
  9. package org.jasig.cas.authentication.handler.captchaImage;
  10. import java.io.IOException;
  11. import javax.servlet.ServletOutputStream;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletResponse;
  14. import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil;
  15. import org.jasig.cas.authentication.handler.util.ValidatorCodeUtil.ValidatorCode;
  16. import org.springframework.beans.factory.InitializingBean;
  17. import org.springframework.web.servlet.ModelAndView;
  18. import org.springframework.web.servlet.mvc.Controller;
  19. import com.sun.image.codec.jpeg.JPEGCodec;
  20. import com.sun.image.codec.jpeg.JPEGImageEncoder;
  21. // import com.wokejia.flow.ValidatorCodeUtil.ValidatorCode;
  22. public class CaptchaImageCreateController implements Controller, InitializingBean {
  23. public void afterPropertiesSet() throws Exception {
  24. }
  25. public ModelAndView handleRequest(HttpServletRequest arg0,
  26. HttpServletResponse response) throws Exception {
  27. ValidatorCode codeUtil = ValidatorCodeUtil.getCode();
  28. System.out.println("code="+codeUtil.getCode());
  29. arg0.getSession().setAttribute("code", codeUtil.getCode());
  30. // 禁止图像缓存。
  31. response.setHeader("Pragma", "no-cache");
  32. response.setHeader("Cache-Control", "no-cache");
  33. response.setDateHeader("Expires", 0);
  34. response.setContentType("image/jpeg");
  35. ServletOutputStream sos = null;
  36. try {
  37. // 将图像输出到Servlet输出流中。
  38. sos = response.getOutputStream();
  39. JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(sos);
  40. encoder.encode(codeUtil.getImage());
  41. sos.flush();
  42. sos.close();
  43. } catch (Exception e) {
  44. } finally {
  45. if (null != sos) {
  46. try {
  47. sos.close();
  48. } catch (IOException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. return null;
  54. }
  55. }

3.开始搞验证码图片生成java类的编写:

这个类中用到了网上经常用的验证码生成类,这个类你可以自己随便写,下面提供一个网上写的,生成的验证码挺漂亮的。

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

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

ValidatorCode类是ValidatorCodeUtil类的一个内部类,代码如下

ValidatorCode.java

  1. /**
  2. * Project Name:casServerHandler
  3. * File Name:ValidatorCodeUtil.java
  4. * Package Name:org.jasig.cas.authentication.handler.util
  5. * Date:2013-4-28下午03:01:38
  6. * Copyright (c) 2013, riambsoft All Rights Reserved.
  7. *
  8. */
  9. package org.jasig.cas.authentication.handler.util;
  10. import java.awt.Color;
  11. import java.awt.Font;
  12. import java.awt.Graphics2D;
  13. import java.awt.image.BufferedImage;
  14. import java.util.Random;
  15. /**
  16. * ClassName:ValidatorCodeUtil <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午03:01:38 <br/>
  17. *
  18. * @author Administrator
  19. * @version
  20. * @since JDK 1.5
  21. * @see
  22. */
  23. public class ValidatorCodeUtil {
  24. public static ValidatorCode getCode() {
  25. // 验证码图片的宽度。
  26. int width = 80;
  27. // 验证码图片的高度。
  28. int height = 30;
  29. BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  30. Graphics2D g = buffImg.createGraphics();
  31. // 创建一个随机数生成器类。
  32. Random random = new Random();
  33. // 设定图像背景色(因为是做背景,所以偏淡)
  34. g.setColor(Color.WHITE);
  35. g.fillRect(0, 0, width, height);
  36. // 创建字体,字体的大小应该根据图片的高度来定。
  37. Font font = new Font("微软雅黑", Font.HANGING_BASELINE, 28);
  38. // 设置字体。
  39. g.setFont(font);
  40. // 画边框。
  41. g.setColor(Color.BLACK);
  42. g.drawRect(0, 0, width - 1, height - 1);
  43. // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到。
  44. // g.setColor(Color.GRAY);
  45. // g.setColor(getRandColor(160, 200));
  46. // for (int i = 0; i < 155; i++) {
  47. // int x = random.nextInt(width);
  48. // int y = random.nextInt(height);
  49. // int xl = random.nextInt(12);
  50. // int yl = random.nextInt(12);
  51. // g.drawLine(x, y, x + xl, y + yl);
  52. // }
  53. // randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
  54. StringBuffer randomCode = new StringBuffer();
  55. // 设置默认生成4个验证码
  56. int length = 4;
  57. // 设置备选验证码:包括"a-z"和数字"0-9"
  58. String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  59. int size = base.length();
  60. // 随机产生4位数字的验证码。
  61. for (int i = 0; i < length; i++) {
  62. // 得到随机产生的验证码数字。
  63. int start = random.nextInt(size);
  64. String strRand = base.substring(start, start + 1);
  65. // 用随机产生的颜色将验证码绘制到图像中。
  66. // 生成随机颜色(因为是做前景,所以偏深)
  67. // g.setColor(getRandColor(1, 100));
  68. // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
  69. g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
  70. g.drawString(strRand, 15 * i + 6, 24);
  71. // 将产生的四个随机数组合在一起。
  72. randomCode.append(strRand);
  73. }
  74. // 图象生效
  75. g.dispose();
  76. ValidatorCode code = new ValidatorCode();
  77. code.image = buffImg;
  78. code.code = randomCode.toString();
  79. return code;
  80. }
  81. // 给定范围获得随机颜色
  82. static Color getRandColor(int fc, int bc) {
  83. Random random = new Random();
  84. if (fc > 255)
  85. fc = 255;
  86. if (bc > 255)
  87. bc = 255;
  88. int r = fc + random.nextInt(bc - fc);
  89. int g = fc + random.nextInt(bc - fc);
  90. int b = fc + random.nextInt(bc - fc);
  91. return new Color(r, g, b);
  92. }
  93. /**
  94. *
  95. * <p class="detail">
  96. * 验证码图片封装
  97. * </p>
  98. *
  99. * @ClassName: ValidatorCode
  100. * @version V1.0
  101. * @date 2012-4-9 下午07:24:14
  102. * @author 罗伟俊
  103. *
  104. */
  105. public static class ValidatorCode {
  106. private BufferedImage image;
  107. private String code;
  108. /**
  109. * <p class="detail">
  110. * 图片流
  111. * </p>
  112. *
  113. * @return
  114. */
  115. public BufferedImage getImage() {
  116. return image;
  117. }
  118. /**
  119. * <p class="detail">
  120. * 验证码
  121. * </p>
  122. *
  123. * @return
  124. */
  125. public String getCode() {
  126. return code;
  127. }
  128. }
  129. }

4.验证码生成做完了,那么我们开始修改默认的认证器的认证方式,增加验证码验证

自己新建一个java类:

ImageVaditeAuthenticationViaFormAction.java,此类其实是改造的org.jasig.cas.web.flow.AuthenticationViaFormAction.java这个类,它里面本来只是验证用户名和密码,我们增加一个成员变量,code,然后在验证用户名和密码之前,我们先开始验证验证码。

  1. /*
  2. * Licensed to Jasig under one or more contributor license
  3. * agreements. See the NOTICE file distributed with this work
  4. * for additional information regarding copyright ownership.
  5. * Jasig licenses this file to you under the Apache License,
  6. * Version 2.0 (the "License"); you may not use this file
  7. * except in compliance with the License.  You may obtain a
  8. * copy of the License at the following location:
  9. *
  10. *   http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied.  See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.jasig.cas.authentication.handler;
  20. import javax.servlet.http.HttpServletRequest;
  21. import javax.servlet.http.HttpServletResponse;
  22. import javax.validation.constraints.NotNull;
  23. import org.jasig.cas.CentralAuthenticationService;
  24. import org.jasig.cas.authentication.handler.AuthenticationException;
  25. import org.jasig.cas.authentication.principal.Credentials;
  26. import org.jasig.cas.authentication.principal.Service;
  27. import org.jasig.cas.ticket.TicketException;
  28. import org.jasig.cas.web.bind.CredentialsBinder;
  29. import org.jasig.cas.web.support.WebUtils;
  30. import org.slf4j.Logger;
  31. import org.slf4j.LoggerFactory;
  32. import org.springframework.binding.message.MessageBuilder;
  33. import org.springframework.binding.message.MessageContext;
  34. import org.springframework.util.StringUtils;
  35. import org.springframework.web.util.CookieGenerator;
  36. import org.springframework.webflow.execution.RequestContext;
  37. /**
  38. * 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.
  39. *
  40. * @author Scott Battaglia
  41. * @version $Revision$ $Date$
  42. * @since 3.0.4
  43. */
  44. public class ImageVaditeAuthenticationViaFormAction {
  45. // 验证码参数:
  46. private String code = "code";
  47. /**
  48. * Binder that allows additional binding of form object beyond Spring defaults.
  49. */
  50. private CredentialsBinder credentialsBinder;
  51. /** Core we delegate to for handling all ticket related tasks. */
  52. @NotNull
  53. private CentralAuthenticationService centralAuthenticationService;
  54. @NotNull
  55. private CookieGenerator warnCookieGenerator;
  56. protected Logger logger = LoggerFactory.getLogger(getClass());
  57. public final void doBind(final RequestContext context, final Credentials credentials) throws Exception {
  58. final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
  59. if (this.credentialsBinder != null && this.credentialsBinder.supports(credentials.getClass())) {
  60. this.credentialsBinder.bind(request, credentials);
  61. }
  62. }
  63. public final String submit(final RequestContext context, final Credentials credentials, final MessageContext messageContext) throws Exception {
  64. // 检测验证码
  65. if (credentials instanceof CaptchaImageLoginCredentials) {
  66. // 这个类也是我们自己搞的,里面能取到验证码
  67. CaptchaImageLoginCredentials rmupc = (CaptchaImageLoginCredentials) credentials;
  68. // 从session中取出生成验证码的时候就保存在session中的验证码
  69. String sessionCode = (String) WebUtils.getHttpServletRequest(context).getSession().getAttribute(code);
  70. // 如果验证码为null
  71. if (rmupc.getCode() == null) {
  72. // 写入日志
  73. logger.warn("验证码为空");
  74. // 错误信息,会在配置文件(messages_zh_CN.properties)里面先定义好
  75. final String code = "login.code.tip";
  76. // 发送错误信息到前台
  77. messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
  78. return "error";
  79. }
  80. // 如果验证码不正确
  81. if (!rmupc.getCode().toUpperCase().equals(sessionCode.toUpperCase())) {
  82. logger.warn("验证码检验有误");
  83. final String code = "login.code.error";
  84. messageContext.addMessage(new MessageBuilder().error().code(code).arg("").defaultText(code).build());
  85. return "error";
  86. }
  87. }
  88. // Validate login ticket
  89. final String authoritativeLoginTicket = WebUtils.getLoginTicketFromFlowScope(context);
  90. final String providedLoginTicket = WebUtils.getLoginTicketFromRequest(context);
  91. if (!authoritativeLoginTicket.equals(providedLoginTicket)) {
  92. this.logger.warn("Invalid login ticket " + providedLoginTicket);
  93. final String code = "INVALID_TICKET";
  94. messageContext.addMessage(new MessageBuilder().error().code(code).arg(providedLoginTicket).defaultText(code).build());
  95. return "error";
  96. }
  97. final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
  98. final Service service = WebUtils.getService(context);
  99. if (StringUtils.hasText(context.getRequestParameters().get("renew")) && ticketGrantingTicketId != null && service != null) {
  100. try {
  101. final String serviceTicketId = this.centralAuthenticationService.grantServiceTicket(ticketGrantingTicketId, service, credentials);
  102. WebUtils.putServiceTicketInRequestScope(context, serviceTicketId);
  103. putWarnCookieIfRequestParameterPresent(context);
  104. return "warn";
  105. } catch (final TicketException e) {
  106. if (isCauseAuthenticationException(e)) {
  107. populateErrorsInstance(e, messageContext);
  108. return getAuthenticationExceptionEventId(e);
  109. }
  110. this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);
  111. if (logger.isDebugEnabled()) {
  112. logger.debug("Attempted to generate a ServiceTicket using renew=true with different credentials", e);
  113. }
  114. }
  115. }
  116. try {
  117. WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials));
  118. putWarnCookieIfRequestParameterPresent(context);
  119. return "success";
  120. } catch (final TicketException e) {
  121. populateErrorsInstance(e, messageContext);
  122. if (isCauseAuthenticationException(e))
  123. return getAuthenticationExceptionEventId(e);
  124. return "error";
  125. }
  126. }
  127. private void populateErrorsInstance(final TicketException e, final MessageContext messageContext) {
  128. try {
  129. messageContext.addMessage(new MessageBuilder().error().code(e.getCode()).defaultText(e.getCode()).build());
  130. } catch (final Exception fe) {
  131. logger.error(fe.getMessage(), fe);
  132. }
  133. }
  134. private void putWarnCookieIfRequestParameterPresent(final RequestContext context) {
  135. final HttpServletResponse response = WebUtils.getHttpServletResponse(context);
  136. if (StringUtils.hasText(context.getExternalContext().getRequestParameterMap().get("warn"))) {
  137. this.warnCookieGenerator.addCookie(response, "true");
  138. } else {
  139. this.warnCookieGenerator.removeCookie(response);
  140. }
  141. }
  142. private AuthenticationException getAuthenticationExceptionAsCause(final TicketException e) {
  143. return (AuthenticationException) e.getCause();
  144. }
  145. private String getAuthenticationExceptionEventId(final TicketException e) {
  146. final AuthenticationException authEx = getAuthenticationExceptionAsCause(e);
  147. if (this.logger.isDebugEnabled())
  148. this.logger.debug("An authentication error has occurred. Returning the event id " + authEx.getType());
  149. return authEx.getType();
  150. }
  151. private boolean isCauseAuthenticationException(final TicketException e) {
  152. return e.getCause() != null && AuthenticationException.class.isAssignableFrom(e.getCause().getClass());
  153. }
  154. public final void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {
  155. this.centralAuthenticationService = centralAuthenticationService;
  156. }
  157. /**
  158. * 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).
  159. *
  160. * @param credentialsBinder
  161. *            the credentials binder to set.
  162. */
  163. public final void setCredentialsBinder(final CredentialsBinder credentialsBinder) {
  164. this.credentialsBinder = credentialsBinder;
  165. }
  166. public final void setWarnCookieGenerator(final CookieGenerator warnCookieGenerator) {
  167. this.warnCookieGenerator = warnCookieGenerator;
  168. }
  169. }
ImageVaditeAuthenticationViaFormAction.java用到了另一个类,也是我们需要改造的类,改造的org.jasig.cas.authentication.principal.UsernamePasswordCredentials.java,你把源码拿出来和这个类对比一下就知道只是增加了一个private String code;

CaptchaImageLoginCredentials.java

  1. /**
  2. * Project Name:casServerHandler
  3. * File Name:CaptchaImageLoginCredentials.java
  4. * Package Name:org.jasig.cas.authentication.handler
  5. * Date:2013-4-28下午06:55:08
  6. * Copyright (c) 2013, riambsoft All Rights Reserved.
  7. *
  8. */
  9. package org.jasig.cas.authentication.handler;
  10. import java.util.Map;
  11. import javax.validation.constraints.NotNull;
  12. import javax.validation.constraints.Size;
  13. import org.jasig.cas.authentication.principal.RememberMeUsernamePasswordCredentials;
  14. /**
  15. * ClassName:CaptchaImageLoginCredentials <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-4-28 下午06:55:08 <br/>
  16. *
  17. * @author Administrator
  18. * @version
  19. * @since JDK 1.5
  20. * @see
  21. */
  22. public class CaptchaImageLoginCredentials extends RememberMeUsernamePasswordCredentials {
  23. private static final long serialVersionUID = 1L;
  24. private Map<String, Object> param;
  25. /** The username. */
  26. @NotNull
  27. @Size(min = 1, message = "验证码为空")
  28. private String code;
  29. public String getCode() {
  30. return code;
  31. }
  32. public void setCode(String code) {
  33. this.code = code;
  34. }
  35. public Map<String, Object> getParam() {
  36. return param;
  37. }
  38. public void setParam(Map<String, Object> param) {
  39. this.param = param;
  40. }
  41. }

5.下面开始对xml文件进行修改:

1)还是刚才那个路径,我们之前修改的xml文件:C:\tomcat7\webapps\casServer\WEB-INF\cas-servlet.xml

  1. <!-- 修改这个bean,变成我们自己的改造后的类
  2. <bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
  3. p:centralAuthenticationService-ref="centralAuthenticationService"
  4. p:warnCookieGenerator-ref="warnCookieGenerator"/>
  5. -->
  6. <bean id="authenticationViaFormAction" class="org.jasig.cas.authentication.handler.ImageVaditeAuthenticationViaFormAction"
  7. p:centralAuthenticationService-ref="centralAuthenticationService"
  8. p:warnCookieGenerator-ref="warnCookieGenerator"/>
  9. <!-- over -->

2)C:\tomcat7\webapps\casServer\WEB-INF\login-webflow.xml

  1. <flow xmlns="http://www.springframework.org/schema/webflow"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://www.springframework.org/schema/webflow
  4. http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
  5. <!-- 替换这个
  6. <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
  7. -->
  8. <var name="credentials" class="org.jasig.cas.authentication.handler.CaptchaImageLoginCredentials" />
  9. <!-- over -->
  10. <on-start>
  11. <evaluate expression="initialFlowSetupAction" />
  12. </on-start>

找到节点:viewLoginForm

  1. <!-- 修改这个
  2. <view-state id="viewLoginForm" view="casLoginView" model="credentials">
  3. <binder>
  4. <binding property="username" />
  5. <binding property="password" />
  6. </binder>
  7. <on-entry>
  8. <set name="viewScope.commandName" value="'credentials'" />
  9. </on-entry>
  10. <transition on="submit" bind="true" validate="true" to="realSubmit">
  11. <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
  12. </transition>
  13. </view-state>
  14. ->
  15. <view-state id="viewLoginForm" view="casLoginView" model="credentials">
  16. <binder>
  17. <binding property="username" />
  18. <binding property="password" />
  19. <binding property="code" />
  20. </binder>
  21. <on-entry>
  22. <set name="viewScope.commandName" value="'credentials'" />
  23. </on-entry>
  24. <transition on="submit" bind="true" validate="true" to="realSubmit">
  25. <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
  26. </transition>
  27. </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的处理

  1. <!-- validate code-->
  2. <servlet-mapping>
  3. <servlet-name>cas</servlet-name>
  4. <url-pattern>/captcha.htm</url-pattern>
  5. </servlet-mapping>
  6. <!--  over-->

这一步很重要,否则首页打开时,根本找不到captacha.htm而不显示图片,我做这个的时候,也是搞了好久,才发现web.xml这么重要的配置忘记写。

5)现在去找你的前台页面C:\tomcat7\webapps\casServer\WEB-INF\view\jsp\default\ui\casLoginView.jsp,给加上验证码的文本框和响应事件吧,比如说看不清楚换一张

  1. <!-- 验证码 -->
  2. <div class="row fl-controls-left">
  3. <label for="code" class="fl-label">验证码:</label>
  4. <script type="text/javascript">
  5. function refresh(){
  6. fm1.vali.src="";
  7. fm1.vali.src="captcha.htm";
  8. //img.src='captcha.htm?t='+new Date().getTime()
  9. }
  10. </script>
  11. <input class="required" type="text" tabindex="3"  id="code" size="10"   name="code"  autocomplete="off"  style="float:left;"/>
  12. <div style="height:30px;width:150px;text-align:center;margin-left:5px; float:left;vertical-align:middle; display: table-cell;">
  13. <a href="javascript:refresh();" onclick="refresh();"  style="width:130px;height:30px;">
  14. <span style="display: block;float:left;width:60px;height:25px;float:left;">
  15. <img id="vali"  width="60" height="30" src="captcha.htm" style="padding-left: 5px;"/>
  16. </span>
  17. <span style="display:block;width:60px;height:100%;float:left;vertical-align:middle; display: table-cell;margin-left:15px;">看不清楚?换一个</span>
  18. </a>
  19. </div>

ok 大功告成,编译完的class这几个文件,统统放入你的server端的各个指定路径下,重启tomcat,回帖感谢各位百度前辈吧。

文中所涉及的xml文件完整版:

下载地址:http://pan.baidu.com/share/link?shareid=439449164&uk=436295647

SSO单点登录系列5:cas单点登录增加验证码功能完整步骤的更多相关文章

  1. cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤

    转:http://blog.csdn.net/ae6623/article/details/8919718 本篇教程cas-server端下载地址:解压后,直接放到tomcat的webapp目录下就能 ...

  2. SSO单点登录系列4:cas-server登录页面自定义修改过程(jsp页面修改)

    落雨 cas 单点登录 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标:    下面是正文: 打开cas的默认首页,映入眼帘的是满眼的中文and英文混杂体,作为一 ...

  3. cas sso单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

    转:http://blog.csdn.net/ae6623/article/details/8848107 1)PPT流程图:ppt下载:http://pan.baidu.com/s/1o7KIlom ...

  4. SSO单点登录系列1:cas客户端源码分析cas-client-java-2.1.1.jar

    落雨 cas 单点登录 希望能给以后来研究cas的兄弟留下一点思路,也算是研究了两天的成果,外国人的代码写的很晦涩,翻译下来也没有时间继续跟进,所以有错误的还请大家跟帖和我讨论,qq 39426378 ...

  5. SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

    落雨 cas 单点登录 一.用户第一次访问web1应用. ps:上图少画了一条线,那一条线,应该再返回来一条,然后再到server端,画少了一步...谢谢提醒.而且,重定向肯定是从浏览器过去的.我写的 ...

  6. cas系列(一)--cas单点登录基本原理

    (这段时间打算做单点登录,因此研究了一些cas资料并作为一个系列记录下来,一来可能会帮助一些人,二来对我自己所学知识也是一个巩固.) 一.为什么要实现单点登录 随着信息化不断发展,企业的信息化过程是一 ...

  7. SSO单点登录一:cas单点登录防止登出退出后刷新后退ticket失效报500错,也有退出后直接重新登录报票根验证错误

    问题1: 我登录了client2,又登录了client3,现在我把client2退出了,在client3里面我F5刷新了一下,结果页面报错: 未能够识别出目标 'ST-41-2VcnVMguCDWJX ...

  8. Office 365实现单点登录系列(5)—配置单点登录

    这是单点登录系列的最后一篇文章,前面4篇文章其实都是在为这篇文章的内容做准备,我把这四篇文章的链接放在下面,如果大家有需要,可以参考我以下的链接: Office 365实现单点登录系列(1)—域环境搭 ...

  9. cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)

    转:http://blog.csdn.net/ae6623/article/details/8861065 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标:    ...

随机推荐

  1. ZJUTACM

    描述 这回是浙江工业大学的ACM程序设计竞赛,欢迎你的到来!但是,请稍等!裁判Joe说了,必须正确回答他的问题,才可以看到PIPI的气球MM,KUKU的气球GG.Joe手上有7张卡片,每张卡片上有一个 ...

  2. 神奇的幻方(NOIP2015)(真·纯模拟)

    原题传送门 这是道SB模拟题,NOIP--难度 直接贴代码 #include<iostream> #include<cstdio> using namespace std; , ...

  3. 华为上机测试题(数字字符串转二进制-java)

    PS:此题满分,可参考 /*  * 题目:数字字符串转二进制 * 描述: 输入一串整数,将每个整数转换为二进制数,如果倒数第三个Bit是“0”,则输出“0”,如果是“1”,则输出“1”. 题目类别: ...

  4. 使用aiohttp的一个小例子

    #!/usr/bin/env python # encoding: utf-8 import aiohttp import asyncio import traceback import time i ...

  5. javascript与mongodb的日期时区问题

    默认情况下,js的日期生成是当地时区,但默认显示是按照GMT显示的: > var c = new Date('2017-10-31 06:00:00'); > c 2017-10-30T2 ...

  6. flask框架基本使用(3)(session与cookies)

    #转载请留言联系 flask 框架基本使用(1):https://www.cnblogs.com/chichung/p/9756935.html flask 框架基本使用(2):https://www ...

  7. Selenium2+python自动化9-CSS定位语法【转载】

    前言 大部分人在使用selenium定位元素时,用的是xpath定位,因为xpath基本能解决定位的需求.css定位往往被忽略掉了,其实css定位也有它的价值,css定位更快,语法更简洁.这一篇css ...

  8. Mac下安装node.js , Ionic

    访问node.js官网(https://nodejs.org/en/download/),下载相应的版本. 下载完,点击安装  [默认目录] Node.js v8.9.3 to /usr/local/ ...

  9. linux文件名匹配

    *   匹配文件名中的任何字符串,包括空字符串. ? 匹配文件名中的任何单个字符. [...]   匹配[ ]中所包含的任何字符. [!...]   匹配[ ]中非感叹号!之后的字符. 如: s*   ...

  10. (2)oracle服务、建库

     一.oracle的服务 oracle 11g安装后服务一般是7到8个 1.Oracle ORCL VSS Writer Service Oracle卷映射拷贝写入服务(非必须启动) 2.Oracle ...