spring security登入驗證
阿新 • • 發佈:2019-02-07
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, 10);
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 1:
throw new DisabledException("使用者被停用");
case 2:
throw new UsernameNotFoundException("使用者被刪除");
case 3:
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);
}
}