Spring-Security 实现黑白名单功能
无情
阅读:844
2021-03-31 17:19:54
评论:0
添加该功能是在原有功能上新增功能: SpringBoot +SpringSecurity+mysql 实现用户数据权限管理
本文仅做重点代码的和相关依赖说明:SpringBoot +SpringSecurity+mysql 实现用户数据权限管理 文章中,我们采用的了分布式架构搭建该项目,导致controller 模块是不存在数据库连接资源(DataSource),由此,我们在controller 模块需要添加关于mysql 的连接和相关配置参数:
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<!-- 数据层 Spring-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
application.properties 添加数据库相关配置参数:
#mysql setting
spring.datasource.url=jdbc:mysql://192.168.1.73:3306/boot-security?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=digipower
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
自定义IP黑白名单相关实体文件和查询接口:
package com.zzg.security.ip;
import java.io.Serializable;
import java.util.Date;
/**
* 黑白IP对象
* @author zzg
*
*/
@SuppressWarnings("serial")
public class IpRoster implements Serializable {
private Long id;
private String ip;
private Date date;
public IpRoster(){
super();
}
// 构造函数
public IpRoster(Long id, String ip, Date date) {
super();
this.id = id;
this.ip = ip;
this.date = date;
}
// set 和 get 方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
package com.zzg.security.ip;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
/**
* RowMapper 转换IpRoster 实体对象
* @author zzg
*
*/
public class IpRosterMapper implements RowMapper<IpRoster> {
@Override
public IpRoster mapRow(ResultSet rs, int rowNum) throws SQLException {
// TODO Auto-generated method stub
IpRoster object = new IpRoster();
object.setId(rs.getLong("id"));
object.setIp(rs.getString("ip"));
object.setDate(rs.getDate("date"));
return object;
}
}
package com.zzg.security.ip;
import java.util.List;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* IP黑白名单数据库查询
* @author zzg
*
*/
public class IpRosterRepositoryImpl extends JdbcDaoSupport {
public static final String DEF_SELECT_IP_SQL ="select id, ip, date from ip_roster";
public List<IpRoster> getAllIpRoster(){
return getJdbcTemplate().query(DEF_SELECT_IP_SQL, new IpRosterMapper());
}
}
自定义认证器,添加验证用户IP是否在黑白名单中:
package com.zzg.security.provider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import com.zzg.security.ip.IpRoster;
import com.zzg.security.ip.IpRosterRepositoryImpl;
import com.zzg.security.userservice.AuthUserDetails;
import com.zzg.security.userservice.CustomUserService;
/**
*自定义身份验证提供者
*
* @author zzg
*
*/
@Component
public class SpringSecurityProvider implements AuthenticationProvider {
@Autowired
private CustomUserService userDetailService;
@Autowired
private DataSource dataSource; // 数据源
private IpRosterRepositoryImpl ip; // IP 黑白名单查询
private List<String> black_white = new ArrayList<>();
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// TODO Auto-generated method stub
// 检查用户IP
WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
String userIp = details.getRemoteAddress();
// 黑白名单初始化数据
if(ip == null){
ip = new IpRosterRepositoryImpl();
ip.setDataSource(dataSource); // 设定数据源
}
List<IpRoster> list = ip.getAllIpRoster();
if(list != null && list.size() > 0){
black_white = list.stream().map(IpRoster::getIp).collect(Collectors.toList());
}
// 判断用户IP 是否在黑白名单中
if(black_white.contains(userIp)){
throw new BadCredentialsException("非法 IP 地址");
}
String userName = authentication.getName();
String password = (String) authentication.getCredentials();
// 查询用户权限信息
AuthUserDetails userInfo = (AuthUserDetails) userDetailService.loadUserByUsername(userName);
if (userInfo == null) {
throw new UsernameNotFoundException("");
}
// 密码判断
String encodePwd = DigestUtils.md5Hex(password).toUpperCase();
if (!userInfo.getPassword().equals(encodePwd)) {
throw new BadCredentialsException("");
}
return new UsernamePasswordAuthenticationToken(userInfo, userInfo.getPassword(),
userInfo.getAuthorities());
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
// 拓展获取用户查询服务
public UserDetailsService getUserDetailsService(){
return this.userDetailService;
}
}
补全黑白名单的SQL脚本:
DROP TABLE IF EXISTS `persistent_logins`;
CREATE TABLE `persistent_logins` (
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`series` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`token` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`last_used` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0),
PRIMARY KEY (`series`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。