一、验证码集成

采用谷歌的验证码方案,仅为简单示意

pom文件引入:

  1. <!--谷歌验证码-->
  2. <dependency>
  3. <groupId>com.github.penggle</groupId>
  4. <artifactId>kaptcha</artifactId>
  5. <version>2.3.2</version>
  6. </dependency>

web.xml增加servlet:

  <!-- Kaptcha验证码 -->
  <servlet>
    <servlet-name>Kaptcha</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    <init-param>
      <param-name>kaptcha.border</param-name>
      <param-value>no</param-value>
    </init-param>
    <init-param>
      <param-name>kaptcha.textproducer.char.space</param-name>
      <param-value>4</param-value>
    </init-param>
    <init-param>
      <param-name>kaptcha.textproducer.char.length</param-name>
      <param-value>4</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Kaptcha</servlet-name>
    <url-pattern>/captcha.png</url-pattern>
  </servlet-mapping>
  <!-- Kaptcha验证码 end-->

登录页面表单增加验证码:

<!-- authcode -->
<div class="form-group">
  <label class="control-label col-lg-3" for="password">验证码</label>
  <div class="col-lg-4">
    <input type="text" class="form-control" id="authcode" name="authcode" placeholder="输入验证码" maxlength="4">
  </div>
  <div class="col-lg-5">
    <img class="col-lg-12" onclick="this.src='captcha.png?'+Math.random()" src="captcha.png">
  </div>
</div>

页面效果:
image.png

二、验证码验证

验证码提交,并再后台验证,有两种方式: 1、request获取验证码并验证 2、验证码绑定到CAS表单,并在后台验证

页面js判空验证

layui.use('layer', function(){
  var layer = layui.layer;
});
//用户登录时的校验
function check(form){

    if(form.username.value==''){
        layer.tips("请输入用户名","#username");
        location.href="#username";
        return false;
    }
    if(form.password.value==''){
        layer.tips("请输入密码","#password");
        location.href="#password";
        return false;
    }
    if(form.authcode.value==''){
        layer.tips("请输入验证码","#username");
        location.href="#authcode";
        return false;
    }
    return true;    
}

2.1、request获取并验证

SaaSAuthenticationHandler:这是我们自定义的认证实现

//用户验证之前,先验证验证码
if(!validatorCode(request.getParameter("authcode"))){
    request.setAttribute("msg", "验证码错误");
    request.setAttribute("password", password);
    throw new FailedLoginException();
}
/**
* 验证码验证工具
* @param authcodeInput
* @return
*/
private boolean validatorCode(String authcodeInput) {

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    HttpSession session = request.getSession();
    //session中获取谷歌验证码
    String authcode = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
    session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);//验证一次即作废
    if (StringUtils.isEmpty(authcodeInput) || StringUtils.isEmpty(authcode)) {
        System.out.println("验证码为空OR验证码未生成");
    }
    if (authcode.equals(authcodeInput)) {
        System.out.println("验证码正确");
        return true;
    }
    return false;
}

页面效果
image.png

2.2、验证码绑定到CAS表单

login-webflow.xml

<!--将原有的表单验证注释掉,增加一个我们自己的-->
<!-- <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential"/> -->
    <var name="credential" class="com.mac.sso.bean.UsernamePasswordCredentialWithAuthCode"/>
.....

<view-state id="viewLoginForm" view="#{switchLoginViewAction.checkLoginView(flowRequestContext)}" model="credential">
  <binder>
    <binding property="username" />
    <binding property="password" />
    <!-- 前台添加表单添加验证码字段authcode -->
    <binding property="authcode" required="true"/>
  </binder>
  <on-entry>
    <set name="viewScope.commandName" value="'credential'" />
  </on-entry>
  <transition on="submit" bind="true" validate="true" to="realSubmit">
    <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" />
  </transition>
</view-state>

UsernamePasswordCredentialWithAuthCode

package com.mac.sso.bean;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.jasig.cas.authentication.UsernamePasswordCredential;
/**
 * @author: byy
 * @date : 2017年12月4日 上午11:54:20
 * @Description:带验证码的登陆页面
 */
public class UsernamePasswordCredentialWithAuthCode extends UsernamePasswordCredential {
    private static final long serialVersionUID = 1L;
    //验证码
    @NotNull
    @Size(min = 1, message = "required.authcode")
    private String authcode;
    public final String getAuthcode() {
        return authcode;
    }
    public final void setAuthcode(String authcode) {
        this.authcode = authcode;
    }
}

SaaSAuthenticationHandler:这是我们自定义的认证实现

//用户验证之前,先验证验证码
if(!validatorCode(transformedCredential)){
    request.setAttribute("msg", "验证码错误");
    request.setAttribute("password", password);
    throw new FailedLoginException();
}
/**
* 验证码验证工具
* @param transformedCredential
* @return
*/
private boolean validatorCode(UsernamePasswordCredential transformedCredential) {
    UsernamePasswordCredentialWithAuthCode upc = (UsernamePasswordCredentialWithAuthCode) transformedCredential;
    String submitAuthcode = upc.getAuthcode();

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    HttpSession session = request.getSession();
    //session中获取谷歌验证码
    String authcode = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
    session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);//验证一次即作废
    if (StringUtils.isEmpty(submitAuthcode) || StringUtils.isEmpty(authcode)) {
        System.out.println("验证码为空OR验证码未生成");
    }
    if (submitAuthcode.equals(authcode)) {
        System.out.println("验证码正确");
        return true;
    }
    return false;
}

效果演示:
image.png


教程写到这里基本上已经可以满足可用,下一篇:**客户端集成实战