天天看點

spring security登入驗證

import com.qingxing.ManagerComplex.api.util.DateUtils;
import com.qingxing.ManagerComplex.api.util.LogUtil;
import com.qingxing.ManagerComplex.api.web.sms.service.SmsVerifyCodeService;
import com.qingxing.ManagerComplex.api.web.usermanager.moodel.Authority;
import com.qingxing.ManagerComplex.api.web.usermanager.service.AuthorityOperations;
import com.qingxing.ManagerComplex.api.web.usermanager.service.UserOperator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.*;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 采用存儲過程提供授權
 * <p>
 * Created by zhangxh on 2017/3/13.
 */
public class StoredProcedureAuthenticationProvider implements AuthenticationProvider {

  private static final Logger log = LoggerFactory.getLogger(StoredProcedureAuthenticationProvider.class);

  private JdbcTemplate jdbcTemplate;

  @SuppressWarnings("deprecation")
  private org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder = new ShaPasswordEncoder();

  @Value("${app.sms.loginRequired}")
  private boolean smsLogin;

  @Value("${app.security.salt}")
  private String salt;

  @Inject
  public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
  }

  @Inject
  private SmsVerifyCodeService smsVerifyCodeService;

  @Inject
  private UserOperator userOperator;

  @Inject
  private AuthorityOperations authorityOperations;

  private RowMapper<User> userRowMapper = new RowMapper<User>() {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
      String username = rs.getString("username");
      String password = "";
      User user = new User(username, password);
      user.setArea(rs.getString("area"));
      user.setUsbKeySecretkey(rs.getString("usbkeysecretkey"));
      user.setRealName(rs.getString("realname"));
      user.setMobile(rs.getString("mobile"));
      user.setRoleName(rs.getString("rolename"));
      user.setState(rs.getInt("state"));
      user.setCreateTime(DateUtils.utilDateFromTimestamp(rs.getTimestamp("createtime")));
      user.setErrorCount(rs.getInt("errorcount"));
      user.setUnlockTime(DateUtils.utilDateFromTimestamp(rs.getTimestamp("unlocktime")));
      user.setIp(rs.getString("IP"));
      return user;
    }
  };

  @Override
  public Authentication authenticate(Authentication authentication)
    throws AuthenticationException {
    ServletRequestAttributes attributes =
      (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    String name = authentication.getName();
    String password = authentication.getCredentials().toString();
    HashMap<String, String> details = (HashMap<String, String>) authentication.getDetails();
    String verifyCode = details.get("verify_code");
    String verifyType = details.get("verify_type");
    password = passwordEncoder.encodePassword(password, salt);
    String sql = "select * from  tb_userinfo t  where  t.username =? AND t.password =?";
    Date now = new Date();
    Date limitTime = org.apache.commons.lang3.time.DateUtils.addMinutes(now, );
    User user;
    try {
      user = jdbcTemplate.queryForObject(sql, userRowMapper, name, password);
    } catch (DataAccessException e) {
      sql = "update tb_userinfo  t  set t.errorcount = t.errorcount+1 where t.username = ?";
      jdbcTemplate.update(sql, name);
      sql = "update tb_userinfo  t  set t.state=3,t.unlocktime = ? where t.username = ? AND t.errorcount >= 3";
      jdbcTemplate.update(sql, limitTime, name);
      throw new UsernameNotFoundException("使用者名或者密碼錯誤");
    }

    if (user.getUnlockTime() != null) {
      if (user.getUnlockTime().getTime() > now.getTime()) {
        throw new LockedException("使用者被鎖定");
      }
      sql = "update tb_userinfo  t  set t.errorcount =0,t.state=0,t.unlocktime=NULL where t.username = ?";
      jdbcTemplate.update(sql, name);
    }
    switch (user.getState()) {
      case :
        throw new DisabledException("使用者被停用");
      case :
        throw new UsernameNotFoundException("使用者被删除");
      case :
        throw new LockedException("使用者被鎖定");
      default:
        break;
    }
    sql = "update tb_userinfo  t  set t.errorcount =0 where t.username = ?";
    jdbcTemplate.update(sql, name);
    if (smsLogin && StringUtils.isNotBlank(user.getMobile()) &&
      !smsVerifyCodeService.checkVerifyCodeByPhone(userOperator.getPhone(name), verifyCode, verifyType)) {
      throw new BadCredentialsException("短信驗證碼錯誤");
    }

    // 添加使用者權限
    List<GrantedAuthority> grantedAuths = new ArrayList<>();
    grantedAuths.add(new SimpleGrantedAuthority("ROLE_" + user.getRoleName()));

    // 添加使用者權限進去
    List<Authority> auths = authorityOperations.queryAuthorityByRoleName(user.getRoleName());
    // 循環添加所有權限
    for (Authority auth : auths) {
      grantedAuths.add(new SimpleGrantedAuthority(auth.getPath()));
    }
    user.setAuthorities(grantedAuths);
    // 記錄登入操作
    String realarea = LogUtil.sqlArea(user.getArea());
    String ip1 = LogUtil.getIpAddress(request);
    sql = "INSERT INTO tb_logging (area, username, ip, path, operation, createdate)"
      + "VALUES (?,?,?,?,?,?)";
    jdbcTemplate.update(sql, realarea, name, ip1, "登入", "登入成功", new Date());
    log.debug("區域" + realarea + " 使用者名:" + name + " ip位址: " + ip1 + " ,操作:登入成功" + ", 操作時間為:"
      + new Date());

    return new UsernamePasswordAuthenticationToken(user, password, grantedAuths);

  }


  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
  }
}