Package com.github.dactiv.showcase.service.account

Source Code of com.github.dactiv.showcase.service.account.CaptchaAuthenticationFilter

package com.github.dactiv.showcase.service.account;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Component;

import com.github.dactiv.showcase.common.SystemVariableUtils;

/**
* 验证码登录认证Filter
*
* @author maurice
*
*/
@Component
public class CaptchaAuthenticationFilter extends FormAuthenticationFilter{
 
  /**
   * 默认验证码参数名称
   */
  public static final String DEFAULT_CAPTCHA_PARAM = "captcha";
 
  /**
   * 默认在session中存储的登录错误次数的名称
   */
  private static final String DEFAULT_LOGIN_INCORRECT_NUMBER_KEY_ATTRIBUTE = "incorrectNumber";
 
  //验证码参数名称
    private String captchaParam = DEFAULT_CAPTCHA_PARAM;
    //在session中的存储验证码的key名称
    private String sessionCaptchaKeyAttribute = DEFAULT_CAPTCHA_PARAM;
    //在session中存储的登录错误次数名称
    private String loginIncorrectNumberKeyAttribute = DEFAULT_LOGIN_INCORRECT_NUMBER_KEY_ATTRIBUTE;
    //允许登录错误次数,当登录次数大于该数值时,会在页面中显示验证码
    private Integer allowIncorrectNumber = 1;
   
    /**
     * 重写父类方法,在shiro执行登录时先对比验证码,正确后在登录,否则直接登录失败
     */
  @Override
  protected boolean executeLogin(ServletRequest request,ServletResponse response) throws Exception {
   
    Session session = SystemVariableUtils.createSessionIfNull();
    //获取登录错误次数
    Integer number = (Integer) session.getAttribute(getLoginIncorrectNumberKeyAttribute());
   
    //首次登录,将该数量记录在session中
    if (number == null) {
      number = new Integer(1);
      session.setAttribute(getLoginIncorrectNumberKeyAttribute(), number);
    }
   
    //如果登录次数大于allowIncorrectNumber,需要判断验证码是否一致
    if (number > getAllowIncorrectNumber()) {
      //获取当前验证码
      String currentCaptcha = (String) session.getAttribute(getSessionCaptchaKeyAttribute());
      //获取用户输入的验证码
      String submitCaptcha = getCaptcha(request);
      //如果验证码不匹配,登录失败
      if (StringUtils.isEmpty(submitCaptcha) || !StringUtils.equals(currentCaptcha,submitCaptcha.toLowerCase())) {
        return onLoginFailure(this.createToken(request, response), new AccountException("验证码不正确"), request, response);
      }
   
    }
   
    return super.executeLogin(request, response);
  }


  /**
   * 重写父类方法,当登录失败将异常信息设置到request的attribute中
   */
  @Override
  protected void setFailureAttribute(ServletRequest request,AuthenticationException ae) {
    if (ae instanceof IncorrectCredentialsException) {
      request.setAttribute(getFailureKeyAttribute(), "登录帐号密码不正确");
    } else {
      request.setAttribute(getFailureKeyAttribute(), ae.getMessage());
    }
  }
 
  /**
   * 重写父类方法,当登录失败后,将allowIncorrectNumber(允许登错误录次) + 1
   */
  @Override
  protected boolean onLoginFailure(AuthenticationToken token,AuthenticationException e, ServletRequest request,ServletResponse response) {
   
    Session session = SystemVariableUtils.getSession();
    Integer number = (Integer) session.getAttribute(getLoginIncorrectNumberKeyAttribute());
    session.setAttribute(getLoginIncorrectNumberKeyAttribute(),++number);
   
    return super.onLoginFailure(token, e, request, response);
  }
 
  /**
   * 重写父类方法,当登录成功后,将allowIncorrectNumber(允许登错误录次)设置为0,重置下一次登录的状态
   */
  @Override
  protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
   
    Session session = SystemVariableUtils.getSession();
    session.removeAttribute(getLoginIncorrectNumberKeyAttribute());
    session.setAttribute("sv", subject.getPrincipal());
   
    return super.onLoginSuccess(token, subject, request, response);
  }

  /**
   * 设置验证码提交的参数名称
   *
   * @param captchaParam 验证码提交的参数名称
   */
  public void setCaptchaParam(String captchaParam) {
    this.captchaParam = captchaParam;
  }

  /**
   * 获取验证码提交的参数名称
   *
   * @return String
   */
  public String getCaptchaParam() {
    return captchaParam;
  }

  /**
   * 设置在session中的存储验证码的key名称
   *
   * @param sessionCaptchaKeyAttribute 存储验证码的key名称
   */
  public void setSessionCaptchaKeyAttribute(String sessionCaptchaKeyAttribute) {
    this.sessionCaptchaKeyAttribute = sessionCaptchaKeyAttribute;
  }
 
  /**
   * 获取设置在session中的存储验证码的key名称
   *
   * @return Sting
   */
  public String getSessionCaptchaKeyAttribute() {
    return sessionCaptchaKeyAttribute;
  }

  /**
   * 获取登录错误次数的key属性名称
   *
   * @return String
   */
  public String getLoginIncorrectNumberKeyAttribute() {
    return loginIncorrectNumberKeyAttribute;
  }

  /**
   * 设置登录错误次数的key属性名称
   *
   * @param loginIncorrectNumberKeyAttribute 属性名称
   */
  public void setLoginIncorrectNumberKeyAttribute(String loginIncorrectNumberKeyAttribute) {
    this.loginIncorrectNumberKeyAttribute = loginIncorrectNumberKeyAttribute;
  }

  /**
   * 获取用户输入的验证码
   *
   * @param request ServletRequest
   *
   * @return String
   */
  public String getCaptcha(ServletRequest request) {
    return WebUtils.getCleanParam(request, getCaptchaParam());
  }
 
  /**
   * 获取允许登录次数
   *
   * @return Integer
   */
  public Integer getAllowIncorrectNumber() {
    return allowIncorrectNumber;
  }

  /**
   * 设置允许登录次数,当登录次数大于该数值时,会在页面中显示验证码
   *
   * @param allowIncorrectNumber 允许登录次数
   */
  public void setAllowIncorrectNumber(Integer allowIncorrectNumber) {
    this.allowIncorrectNumber = allowIncorrectNumber;
  }
 
}
TOP

Related Classes of com.github.dactiv.showcase.service.account.CaptchaAuthenticationFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.