帮我编写完整的SpringBoot2.7.2整合SpringSecurity+Redis rbac权限控制的java代码
时间: 2024-02-09 21:10:58 浏览: 166
基于SpringBoot+SpringSecurity的RBAC管理系统源码
5星 · 资源好评率100%
好的,以下是完整的Spring Boot 2.7.2整合Spring Security + Redis RBAC权限控制的Java代码示例:
首先,您需要在您的Spring Boot项目中添加Spring Security和Redis的依赖。
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```
接下来,创建一个User实体类,该类表示系统中的用户。
```java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements UserDetails {
private static final long serialVersionUID = -8091879091924046844L;
private String username;
private String password;
private List<String> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
```
然后,创建一个UserDetailsServiceImpl类,该类实现了UserDetailsService接口,用于从Redis中获取用户信息。
```java
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = (User) redisTemplate.opsForHash().get("users", username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
return user;
}
}
```
接下来,创建一个RBACAuthorityService类,该类用于从Redis中获取角色和权限信息。
```java
@Service
public class RBACAuthorityService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public List<String> getRolesByUserName(String username) {
return (List<String>) redisTemplate.opsForHash().get("roles", username);
}
public List<String> getPermissionsByRole(String role) {
return (List<String>) redisTemplate.opsForHash().get("permissions", role);
}
}
```
然后,创建一个RBACPermissionEvaluator类,该类实现了PermissionEvaluator接口,用于判断用户是否有权限访问某个URL。
```java
@Component
public class RBACPermissionEvaluator implements PermissionEvaluator {
@Autowired
private RBACAuthorityService rbacAuthorityService;
@Override
public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
if (auth == null || targetDomainObject == null || !(permission instanceof String)) {
return false;
}
String username = auth.getName();
List<String> roles = rbacAuthorityService.getRolesByUserName(username);
for (String role : roles) {
List<String> permissions = rbacAuthorityService.getPermissionsByRole(role);
if (permissions.contains(permission)) {
return true;
}
}
return false;
}
@Override
public boolean hasPermission(Authentication auth, Serializable targetId, String targetType, Object permission) {
return false;
}
}
```
然后,您需要创建一个RedisTokenRepositoryImpl类,该类实现了PersistentTokenRepository接口,用于将Remember-Me令牌存储到Redis中。
```java
@Repository
public class RedisTokenRepositoryImpl implements PersistentTokenRepository {
private RedisTemplate<String, Object> redisTemplate;
public RedisTokenRepositoryImpl(RedisConnectionFactory redisConnectionFactory) {
this.redisTemplate = new RedisTemplate<>();
this.redisTemplate.setConnectionFactory(redisConnectionFactory);
this.redisTemplate.setKeySerializer(new StringRedisSerializer());
this.redisTemplate.setHashKeySerializer(new StringRedisSerializer());
this.redisTemplate.setHashValueSerializer(new GenericToStringSerializer<>(Object.class));
this.redisTemplate.afterPropertiesSet();
}
@Override
public void createNewToken(PersistentRememberMeToken token) {
redisTemplate.opsForHash().put("rememberMeTokens", token.getSeries(), token);
}
@Override
public void updateToken(String series, String tokenValue, Date lastUsed) {
PersistentRememberMeToken token = getTokenForSeries(series);
if (token != null) {
token.setTokenValue(tokenValue);
token.setDate(lastUsed);
redisTemplate.opsForHash().put("rememberMeTokens", series, token);
}
}
@Override
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
return (PersistentRememberMeToken) redisTemplate.opsForHash().get("rememberMeTokens", seriesId);
}
@Override
public void removeUserTokens(String username) {
HashOperations<String, String, PersistentRememberMeToken> ops = redisTemplate.opsForHash();
Map<String, PersistentRememberMeToken> tokens = ops.entries("rememberMeTokens");
for (PersistentRememberMeToken token : tokens.values()) {
if (username.equals(token.getUsername())) {
ops.delete("rememberMeTokens", token.getSeries());
}
}
}
}
```
接下来,创建一个SecurityConfig类,该类用于配置Spring Security。
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private RBACPermissionEvaluator permissionEvaluator;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll()
.and()
.rememberMe()
.tokenRepository(redisTokenRepository())
.tokenValiditySeconds(86400)
.userDetailsService(userDetailsService);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/images/**");
}
@Bean
public RedisTokenRepositoryImpl redisTokenRepository() {
return new RedisTokenRepositoryImpl(redisConnectionFactory);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RBACInterceptor(permissionEvaluator));
}
}
```
在上述代码中,我们使用了RBACPermissionEvaluator来判断用户是否有权限访问某个URL。我们还使用了RedisTokenRepositoryImpl来将Remember-Me令牌存储到Redis中。最后,我们使用了RBACInterceptor来拦截请求并进行权限验证。在addInterceptors方法中,我们将RBACInterceptor注册到Spring MVC拦截器链中。
最后,创建一个RBACInterceptor类,该类实现了HandlerInterceptor接口,用于拦截请求并进行权限验证。
```java
public class RBACInterceptor implements HandlerInterceptor {
private RBACPermissionEvaluator permissionEvaluator;
public RBACInterceptor(RBACPermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String url = request.getRequestURI();
String method = request.getMethod();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
response.sendRedirect("/login");
return false;
}
boolean hasPermission = permissionEvaluator.hasPermission(authentication, url, method);
if (!hasPermission) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return false;
}
return true;
}
}
```
上述代码中,我们使用RBACPermissionEvaluator来判断用户是否有权限访问某个URL。如果用户没有权限访问某个URL,我们将返回HTTP 403 Forbidden错误。
希望这些信息能对您有所帮助!
阅读全文