application.properties
Spring AOP 注解实现权限验证的实战指南
在现代软件开发中,权限控制是一项基本且重要的功能,Spring框架提供了一种优雅的方式来处理权限验证,通过使用AOP(面向切面编程)和注解,我们可以轻松地实现复杂的权限逻辑,本文将详细介绍如何利用Spring AOP注解来实现权限验证。
引入必要的依赖
确保你的项目已经添加了Spring AOP和AspectJ库,可以通过Maven或Gradle来管理依赖,在pom.xml文件中,可以这样引入:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
创建权限接口
为每个需要权限验证的对象创建一个接口,该接口包含检查用户是否具有相应权限的方法,假设我们有一个名为UserManager的服务类,它需要检查用户是否有访问某个资源的权限。
public interface PermissionChecker {
boolean checkPermission(User user, Resource resource);
}
实现权限检查器
根据业务需求,选择合适的权限检查器,这里以UsernamePasswordAuthenticationToken为基础,并结合自定义的权限接口来实现权限验证。
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.List;
public class SecurityUser implements UserDetails {
private static final long serialVersionUID = -842006629181114864L;
private String username;
private List authorities;
public SecurityUser(String username) {
this.username = username;
this.authorities = new ArrayList<>();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
使用AOP进行权限验证
我们将使用Spring AOP注解来增强我们的服务方法,以便它们能够被拦截并执行权限验证逻辑。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class PermissionInterceptor {
private final PermissionChecker permissionChecker;
public PermissionInterceptor(PermissionChecker permissionChecker) {
this.permissionChecker = permissionChecker;
}
@Before("@annotation(permissionCheck)")
public void beforeMethod(Object target, Method method, Object[] args, Class<?>... annos) throws Throwable {
User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (!permissionChecker.checkPermission(currentUser, args[0])) {
throw new AccessDeniedException("Access denied to resource: " + args[0]);
}
}
}
配置Spring Security
最后一步是在配置文件中启用Spring Security,并应用上述权限检查器。
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.security.user.name=admin
spring.security.user.password=admin
spring.security.role-prefix=ROLE_
更新SecurityConfig.java文件中的配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
// Enable AOP interception for security checks
http.addFilterBefore(new RequestValidationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
class RequestValidationFilter extends UsernamePasswordAuthenticationFilter {
public RequestValidationFilter(HttpServletRequest request, HttpServletResponse response,
AuthenticationManager authenticationManager) {
super(request, response, authenticationManager);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authResult);
SecurityContextHolder.setContext(context);
}
}
当你尝试访问未授权资源时,系统会抛出AccessDeniedException,并允许你通过适当的登录页面进入,这个示例展示了如何使用Spring AOP注解有效地实现权限验证,通过这种方式,你可以轻松地扩展权限逻辑,而不需要修改业务代码。

上一篇