AuthorizationFilter
AuthorizationFilter
1、概述
AuthorizationFilter
在整个安全框架中主要负责授权相关的处理。具体来说,AuthorizationFilter
的工作是确定当前请求是否具有访问某个资源的权限。如果用户没有足够的权限访问某个受保护的资源,AuthorizationFilter
将会阻止请求的继续,返回适当的错误响应(如 HTTP 403 Forbidden)。
2、作用
AuthorizationFilter
主要用于:
- 授权检查:它检查用户是否有足够的权限来访问特定的资源或执行某个操作。如果用户未被授权,它将阻止请求,并返回 403 错误。
- 角色或权限控制:根据请求的路径、方法、用户角色或权限等信息来决定用户是否有权访问某个资源。
- 集成自定义权限控制:可以根据具体的业务逻辑进行自定义的权限校验。
3、工作流程
AuthorizationFilter
主要处理的是基于用户的身份(身份验证)来进行资源的授权控制。它的工作流程如下:
3.1、 拦截请求
当一个 HTTP 请求到达过滤器链时,AuthorizationFilter
会根据配置的 URL 路径或方法来确定是否需要进行授权检查。默认情况下,Spring Security 的授权过滤器通常会配置为拦截所有需要权限检查的请求。
3.2、授权校验
AuthorizationFilter
会根据用户的身份信息(通常通过 SecurityContext
中的 Authentication
对象)来检查用户是否具有访问当前请求资源的权限。授权的依据可以是:
- 用户的角色(如
ROLE_USER
、ROLE_ADMIN
) - 用户的权限(如
READ_PRIVILEGE
、WRITE_PRIVILEGE
) - 配置的 URL 访问控制规则(例如,
/admin/**
需要ROLE_ADMIN
)
如果 Authentication
对象为空(即用户未认证),或者用户没有足够的权限,AuthorizationFilter
将会拒绝该请求。
3.3、请求继续或终止
- 如果授权通过:
AuthorizationFilter
允许请求继续传递到下一个过滤器或最终的处理方法。 - 如果授权失败:
AuthorizationFilter
会生成一个适当的响应,通常是 403 Forbidden,表示当前用户没有权限访问该资源。
AccessDeniedHandler
(如果没有权限)
3.4、调用 当用户没有权限访问某个资源时,AuthorizationFilter
会触发 AccessDeniedHandler
进行进一步的处理。默认情况下,Spring Security 会返回一个 HTTP 403 状态码响应,表示资源不可访问。
4、配置和使用
在 Spring Security 中,AuthorizationFilter
主要由 http.authorizeRequests()
进行配置。你可以基于角色、权限、请求路径等进行授权控制。常见的配置项包括:
- 角色/权限控制:通过
.hasRole()
、.hasAuthority()
等方法指定特定的角色或权限要求。 - 请求路径控制:通过
.antMatchers()
或.requestMatchers()
配置受保护的路径。
4.1、示例 1:基于角色进行授权控制
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
// 使用内存中的用户管理服务创建一个用户
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password") // 密码无需加密,使用 {noop} 表示
.roles("USER")
.build(),
User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") // 只有具有 ADMIN 角色的用户可以访问 /admin/**
.antMatchers("/user/**").hasRole("USER") // 只有具有 USER 角色的用户可以访问 /user/**
.anyRequest().authenticated() // 其他请求需要认证
.and()
.formLogin(); // 启用表单登录
return http.build();
}
}
解释:
authorizeRequests()
:配置请求的访问控制。antMatchers()
用于指定 URL 模式,hasRole()
用于指定角色要求。formLogin()
:启用默认的表单登录机制,用户可以通过表单进行身份验证。- 用户通过
user
或admin
登录后,AuthorizationFilter
会检查他们是否有足够的权限访问/admin/**
或/user/**
资源。
4.2、示例 2:基于权限进行授权控制
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
// 配置用户及其权限
return new InMemoryUserDetailsManager(
User.withUsername("reader")
.password("{noop}password")
.authorities("READ_PRIVILEGE")
.build(),
User.withUsername("writer")
.password("{noop}password")
.authorities("WRITE_PRIVILEGE")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/read/**").hasAuthority("READ_PRIVILEGE") // 只有具有 READ_PRIVILEGE 权限的用户可以访问 /read/**
.antMatchers("/write/**").hasAuthority("WRITE_PRIVILEGE") // 只有具有 WRITE_PRIVILEGE 权限的用户可以访问 /write/**
.anyRequest().authenticated() // 其他请求需要认证
.and()
.formLogin(); // 启用表单登录
return http.build();
}
}
解释:
hasAuthority()
:用于基于权限进行授权控制,与角色不同,权限一般通过authorities
来分配。- 配置了两个用户:
reader
用户有READ_PRIVILEGE
权限,writer
用户有WRITE_PRIVILEGE
权限。 AuthorizationFilter
会根据这些权限检查用户是否能够访问/read/**
或/write/**
。
AccessDeniedHandler
)
4.3、示例 3:授权失败处理(Spring Security 6.x 允许你自定义授权失败的处理方式。例如,当用户访问某个受保护的资源时没有足够的权限,系统会返回 403 Forbidden 错误。
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.AccessDeniedException;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
import org.springframework.web.bind.annotation.ResponseStatus;
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.exceptionHandling()
.accessDeniedHandler(new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.sendError(HttpStatus.FORBIDDEN.value(), "Access Denied");
}
});
return http.build();
}
}
解释:
exceptionHandling().accessDeniedHandler()
:设置自定义的AccessDeniedHandler
,当用户未授权访问资源时,返回 403 错误。- 当用户访问
/admin/**
并且没有ADMIN
角色时,AuthorizationFilter
会调用AccessDeniedHandler
返回 403 错误。
4.4、基于自定义表达式的授权控制
如果你需要更加精细的授权控制,例如基于 URL 模式和复杂的条件判断,你可以通过 authorizeHttpRequests()
进行更加灵活的配置。例如:
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
// 配置内存中的用户详情服务
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build(),
User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build()
);
}
// 配置 HTTP 安全,支持自定义授权表达式
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/admin/**").hasRole("ADMIN") // 仅允许 ADMIN 角色访问 /admin/**
.antMatchers("/user/**").hasRole("USER") // 仅允许 USER 角色访问 /user/**
.antMatchers("/**").access("hasRole('USER') and hasAuthority('WRITE_PRIVILEGE')") // 复杂的授权表达式
.anyRequest().authenticated()
)
.formLogin(); // 启用表单登录
return http.build();
}
}
AuthorizationFilter
和 FilterSecurityInterceptor
5. FilterSecurityInterceptor
被弃用,AuthorizationFilter
的授权逻辑通过 SecurityFilterChain
和 HttpSecurity
来配置。在 SecurityFilterChain
中,你可以通过 authorizeHttpRequests()
来设置路径访问控制、角色/权限验证等规则,AuthorizationFilter
会根据这些规则执行授权检查,并且通过 AccessDecisionManager
来做出授权决策。