为了防止cas server被恶意登录及防暴力登录。这里采用验证码校验。为了良好的用户体验,设定当连续登录错误次数达到3次及以上需验证验证码登录。
这里使用开源的kaptcha来做验证码
5.1. 添加kaptcha验证码依赖库
该库并没有上传到maven中央仓库,因此我们需要自行发布到私服,或者使用上面的scope结合systemPath引用,使用这种方式时,在打包的时候不会打到war包里面,因此为了方便起见建议下载下来自行上传到maven私服或安装到本地仓库。 使用下面的命令即可安装到本地仓库
mvn install:install-file -DgroupId=com.google.code.kaptcha -DartifactId=kaptcha -Dversion=2.3.2 -Dfile=E:\\cas-4.0.0\\cas-server-webapp\\lib\\kaptcha-2.3.2.jar -Dpackaging=jar -DgeneratePom=true
5.2. 配置web.xml
在src\\main\\webapp\\WEB-INF\\web.xml中添加如下内容
创建UsernamePasswordCaptchaCredential继org.jasig.cas.authentication.RememberMeUsernamePasswordCredential
主要是拓展了一个验证字段captcha. @NotNull
@Size(min = 1, message = \private String captcha;
承
自
5.4. 修改cas登录页,添加验证码字段
修改src\\main\\webapp\\WEB-INF\\view\\jsp\\default\%ui\\casLoginView.jsp添加验证码及记住密码字段
--> 记住登录状态 注意表单中的name字段与UsernamePasswordCaptchaCredential中的字段对应。这里在验证码这块使用了c标签判断了错误次数count 。该count在下文会有交代。5.5. 添加验证码校验
在org.jasig.cas.web.flow包下创建CaptchaVaditeAuthenticationViaFormAction并继承自AuthenticationViaFormAction
其具体内容如下: package org.jasig.cas.web.flow; import org.jasig.cas.authentication.Credential; import org.jasig.cas.authentication.UsernamePasswordCaptchaCredential; import org.jasig.cas.web.support.WebUtils; import org.springframework.binding.message.MessageBuilder; import org.springframework.binding.message.MessageContext; import org.springframework.util.StringUtils; import org.springframework.webflow.execution.RequestContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * 验证码校验 * Created by fengjing on 2016/4/27. */ public class CaptchaVaditeAuthenticationViaFormAction extends AuthenticationViaFormAction { private static final String CAPTCHA_REQUIRED_MSG = \验证码必填 private static final String CAPTCHA_ERROR_MSG = \验证码不正确 public final String validate(final RequestContext context, final Credential credentials, final MessageContext messageContext) throws Exception { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); HttpSession session = request.getSession(); // 用户输入错误次数累计,次数大于3次则显示验证码 int count; try { count = (Integer) context.getFlowScope().get(\ } catch (Exception e) { count = 0; } // 获取用户名密码 String username = request.getParameter(\ String password = request.getParameter(\ // 用户名非空验证 if (StringUtils.isEmpty(username)) { populateErrorsInstance(\ count++; context.getFlowScope().put(\ return \ } // 密码非空验证 if (StringUtils.isEmpty(password)) { populateErrorsInstance(\ count++; context.getFlowScope().put(\ return \ } // 验证码判断 String showCaptcha = request.getParameter(\ // 判断验证码是否显示 if (StringUtils.hasText(showCaptcha)) { // 从session中获取验证码 String authcode = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); UsernamePasswordCaptchaCredential upc = (UsernamePasswordCaptchaCredential) credentials; // 获取用户输入的验证码 String submitAuthcode = upc.getCaptcha(); // 验证码非空判断 if (!StringUtils.hasText(submitAuthcode) || !StringUtils.hasText(authcode)) { populateErrorsInstance(CAPTCHA_REQUIRED_MSG, messageContext); count++; context.getFlowScope().put(\ return \ } // 验证码正确性判断 if (submitAuthcode.equals(authcode)) { return \ } else { populateErrorsInstance(CAPTCHA_ERROR_MSG, messageContext); count++; context.getFlowScope().put(\ return \ } } return \ } private void populateErrorsInstance(final String errorCode, final MessageContext messageContext) { try { messageContext.addMessage(new MessageBuilder().error().code(errorCode).defaultText(errorCode).build()); } catch (final Exception fe) { logger.error(fe.getMessage(), fe); } } } 5.6. 自定义异常处理Handler 统计错误次数
在org.jasig.cas.web.flow包下创建MyAuthenticationExceptionHandler。重写handle方法,着重在这里处理计算错误次数 public String handle(final RequestContext context, final AuthenticationException e, final MessageContext messageContext) { int count; try { count = (Integer) context.getFlowScope().get(\} catch (Exception ex) { count = 0; } if (e != null) { for (final Class extends Exception> kind : this.errors) { for (final Class extends Exception> handlerError : e.getHandlerErrors().values()) { if (handlerError != null && handlerError.equals(kind)) { final String messageCode = this.messageBundlePrefix + handlerError.getSimpleName(); messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());