推荐答案
Spring Security 通过一系列的过滤器链来实现认证和授权。认证是验证用户身份的过程,而授权是确定用户是否有权限访问特定资源的过程。
认证流程
- 用户提交凭证:用户通过表单或HTTP Basic认证提交用户名和密码。
- 过滤器链处理:
UsernamePasswordAuthenticationFilter捕获请求并提取凭证。 - 认证管理器:
AuthenticationManager负责处理认证请求,调用AuthenticationProvider进行实际认证。 - 用户详情服务:
UserDetailsService从数据库或其他存储中加载用户信息。 - 密码编码器:
PasswordEncoder用于验证用户密码。 - 认证成功或失败:如果认证成功,
SecurityContextHolder中会设置Authentication对象;如果失败,抛出AuthenticationException。
授权流程
- 请求拦截:
FilterSecurityInterceptor拦截请求并检查用户是否有权限访问资源。 - 访问决策管理器:
AccessDecisionManager决定是否允许访问,通常使用AffirmativeBased策略。 - 投票器:
AccessDecisionVoter对请求进行投票,决定是否允许访问。 - 授权成功或失败:如果授权成功,请求继续;如果失败,抛出
AccessDeniedException。
本题详细解读
认证(Authentication)
认证是验证用户身份的过程。Spring Security 提供了多种认证机制,如表单登录、HTTP Basic 认证、OAuth2 等。
关键组件
- AuthenticationManager:负责处理认证请求,通常由
ProviderManager实现。 - AuthenticationProvider:实际执行认证逻辑,如
DaoAuthenticationProvider。 - UserDetailsService:加载用户信息,通常从数据库加载。
- PasswordEncoder:用于密码的加密和验证,如
BCryptPasswordEncoder。
认证流程
- 用户提交凭证(如用户名和密码)。
UsernamePasswordAuthenticationFilter捕获请求并提取凭证。AuthenticationManager调用AuthenticationProvider进行认证。UserDetailsService加载用户信息。PasswordEncoder验证密码。- 如果认证成功,
SecurityContextHolder中设置Authentication对象;如果失败,抛出AuthenticationException。
授权(Authorization)
授权是确定用户是否有权限访问特定资源的过程。Spring Security 通过 FilterSecurityInterceptor 和 AccessDecisionManager 来实现授权。
关键组件
- FilterSecurityInterceptor:拦截请求并检查权限。
- AccessDecisionManager:决定是否允许访问,通常使用
AffirmativeBased策略。 - AccessDecisionVoter:对请求进行投票,决定是否允许访问。
授权流程
FilterSecurityInterceptor拦截请求。AccessDecisionManager调用AccessDecisionVoter进行投票。- 如果投票结果为允许访问,请求继续;如果拒绝,抛出
AccessDeniedException。
配置示例
// www.javascriptcn.com code example
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user").password(passwordEncoder().encode("password")).roles("USER").build(),
User.withUsername("admin").password(passwordEncoder().encode("password")).roles("ADMIN").build()
);
}
}在这个配置中,我们定义了用户认证和授权的规则,使用 BCryptPasswordEncoder 进行密码加密,并通过 InMemoryUserDetailsManager 管理用户信息。