|
|
package com.tianbo.warehouse.security.login;
|
|
|
|
|
|
import com.tianbo.warehouse.dao.USERSMapper;
|
|
|
import com.tianbo.warehouse.model.USERS;
|
|
|
import com.tianbo.warehouse.security.CustomUserDetailService;
|
|
|
import com.tianbo.warehouse.security.config.SM3PasswordEncoder;
|
|
|
import com.tianbo.warehouse.util.RedisUtils;
|
|
|
import org.apache.shiro.codec.CodecException;
|
|
|
import org.apache.shiro.crypto.hash.Hash;
|
|
|
import org.apache.shiro.crypto.hash.SimpleHash;
|
|
|
import org.apache.shiro.util.ByteSource;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.security.authentication.AuthenticationProvider;
|
|
|
import org.springframework.security.authentication.BadCredentialsException;
|
|
|
import org.springframework.security.authentication.DisabledException;
|
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
|
import org.springframework.security.core.Authentication;
|
|
|
import org.springframework.security.core.AuthenticationException;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
import javax.annotation.Resource;
|
|
|
import java.util.Arrays;
|
|
|
import org.apache.shiro.codec.CodecSupport;
|
|
|
|
|
|
/**
|
|
|
* 自定义认证处理类
|
|
|
*/
|
|
|
@Component
|
|
|
public class MyLoginAuthenticationProvider extends CodecSupport implements AuthenticationProvider {
|
|
|
|
|
|
@Autowired
|
|
|
private CustomUserDetailService userDetailsService;
|
|
|
|
|
|
@Resource
|
|
|
private USERSMapper userMapper;
|
|
|
|
|
|
@Autowired
|
|
|
private RedisUtils redisUtils;
|
|
|
|
|
|
@Autowired
|
|
|
SM3PasswordEncoder sm3PasswordEncoder;
|
|
|
|
|
|
@Override
|
|
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
|
|
// 获取前端表单中输入后返回的用户名、密码
|
|
|
String userName = (String) authentication.getPrincipal();
|
|
|
String password = (String) authentication.getCredentials();
|
|
|
USERS userInfo = (USERS) userDetailsService.loadUserByUsername(userName);
|
|
|
//验证登录密码是否符合规则,如位数包含的字符等
|
|
|
boolean isValid = true;
|
|
|
// 验证密码
|
|
|
if (!isValid) {
|
|
|
//todo: 登录次数超了 锁定账户
|
|
|
throw new BadCredentialsException("密码错误!");
|
|
|
}
|
|
|
if(!userInfo.isEnabled()){
|
|
|
throw new DisabledException("用户被禁用");
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* ----------------
|
|
|
*/
|
|
|
|
|
|
//取盐规则
|
|
|
byte[] salt = PasswordSaltUtils.getSalt16(userInfo.getPassword());
|
|
|
//真实密码
|
|
|
String realPass = PasswordSaltUtils.getPassword16(userInfo.getPassword());
|
|
|
//用户登录密码与盐运算
|
|
|
Object tokenHashedCredentials = this.hashProvidedCredentials(password,salt,1024);
|
|
|
|
|
|
/**
|
|
|
* ----------------
|
|
|
*/
|
|
|
|
|
|
try{
|
|
|
String loginUserLock = redisUtils.get("user:lock:"+userName);
|
|
|
Integer loginUserLockNO= 0;
|
|
|
if (loginUserLock!=null){
|
|
|
loginUserLockNO = Integer.valueOf(loginUserLock);
|
|
|
}
|
|
|
//判断密码是否正确
|
|
|
String sm3EncodePassword = sm3PasswordEncoder.encode(password);
|
|
|
if(!sm3PasswordEncoder.matches(password,userInfo.getPassword())){
|
|
|
redisUtils.set("user:lock:"+userName, String.valueOf(++loginUserLockNO),120);
|
|
|
|
|
|
//两分钟内错误登录次数超过5次锁定账户
|
|
|
if (loginUserLockNO>5){
|
|
|
USERS user = new USERS();
|
|
|
user.setUsername(userName);
|
|
|
user.setUserId(userInfo.getUserId());
|
|
|
//锁定用户
|
|
|
user.setState(false);
|
|
|
userMapper.updateByPrimaryKeySelective(user);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
}catch (Exception e){
|
|
|
throw new BadCredentialsException("验证失败!");
|
|
|
}
|
|
|
|
|
|
|
|
|
// 前后端分离情况下 处理逻辑...
|
|
|
// 更新登录令牌 - 之后访问系统其它接口直接通过token认证用户权限...
|
|
|
return new UsernamePasswordAuthenticationToken(userInfo, password, userInfo.getAuthorities());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public boolean supports(Class<?> aClass) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据用户密码生成秘文
|
|
|
* @param credentials 用户登录密码
|
|
|
* @param salt 盐
|
|
|
* @param hashIterations 1024
|
|
|
* @return
|
|
|
*/
|
|
|
protected Hash hashProvidedCredentials(Object credentials, Object salt, int hashIterations) {
|
|
|
String hashAlgorithmName = "SHA-1";
|
|
|
hashIterations = 1024;
|
|
|
return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
|
|
|
}
|
|
|
|
|
|
protected boolean equals(Object tokenCredentials, Object accountCredentials) {
|
|
|
|
|
|
if (this.isByteSource(tokenCredentials) && this.isByteSource(accountCredentials)) {
|
|
|
|
|
|
byte[] tokenBytes = this.toBytes(tokenCredentials);
|
|
|
byte[] accountBytes = this.toBytes(accountCredentials);
|
|
|
return Arrays.equals(tokenBytes, accountBytes);
|
|
|
} else {
|
|
|
return accountCredentials.equals(tokenCredentials);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|