文章目录
认证相关
核心类理解
1.GrantedAuthority:表示授予对象的权限,通过getAuthority获得String
2.UserDetailsService接口
:表示加载用户信息的服务,通过loadUserByUsername(String username)方法加载返回UserDetails类
3.UserDetailsManager:是UserDetailsService的拓展,提供UserDetails的增删改等操作,实现类InMemoryUserDetailsManager(内存)和JdbcUserDetailsManager(持久层)
4.AuthenticationProvider
:调用UserDetailService中的方法获得库中用户信息,验证传入的Authentication是否匹配库中信息
5.ProviderManager:继承AuthenticationManager,管理多个AuthenticationProvider,遍历调用其中服务提供者的support方法,满足则调用authenticate方法
UserDetails
提供核心用户信息
public interface UserDetails extends Serializable {
// 返回授予用户的权限,不能为null
Collection<? extends GrantedAuthority> getAuthorities();
// 用户名密码
String getPassword();
String getUsername();
}
InMemoryUserDetailsManager
用于在内存中存放用户信息,并对用户信息进行校验等处理
public class InMemoryUserDetailsManager implements UserDetailsManager,
UserDetailsPasswordService {
// 存放当前内存中的用户信息
private final Map<String, MutableUserDetails> users = new HashMap<>();
private AuthenticationManager authenticationManager;
}
AbstractAuthenticationProcessingFilter(认证入口)
用户认证的过滤器,用于处理基于浏览器交互的HTTP验证请求
1.将请求信息封装为Authentication,交付给AuthenticationManager验证
2.提供验证成功和失败的处理,失败清除SecurityContext调用对应失败处理器,成功添加令牌到SecurityContext并发布InteractiveAuthenticationSuccessEvent事件
public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
implements ApplicationEventPublisherAware, MessageSourceAware {
// 事件发布器,验证发布InteractiveAuthenticationSuccessEvent
protected ApplicationEventPublisher eventPublisher;
// 核心验证
private AuthenticationManager authenticationManager;
// 匹配的请求
private RequestMatcher requiresAuthenticationRequestMatcher;
// 验证成功或失败的处理器
private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
// 记住我和Session实现
private RememberMeServices rememberMeServices = new NullRememberMeServices();
private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
}
// 核心过滤处理
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 如果请求不匹配则跳过
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
Authentication authResult;
try {
// 从请求中解析用户信息(Authentication),添加自定义detail信息,交给AuthenticationManager验证
authResult = attemptAuthentication(request, response);
if (authResult == null) {
// 立即返回,因为子类指示它尚未完成
return;
}
// Session处理
sessionStrategy.onAuthentication(authResult, request, response);
}
···异常捕获,调用unsuccessfulAuthentication(request, response, failed)方法处理
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
// 验证成功处理
successfulAuthentication(request, response, chain, authResult);
}
例子
public static void main(String... args) {
// 输入的身份信息
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "pwd");
// 提供验证服务
DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
// 创建内存获取用户信息的服务
InMemoryUserDetailsManager memory = new InMemoryUserDetailsManager();
// 在内存中存放一条用户信息,{noop}存放密码的加密方式,此处不加密
memory.createUser(User.withUsername("user").password("{noop}pwd").roles("users","system").build());
// 将查询用户信息服务放入验证服务中
daoProvider.setUserDetailsService(memory);
// 对所有提供的服务进行管理
AuthenticationManager am = new ProviderManager(daoProvider);
// 对输入的信息进行验证
Authentication authenticate = am.authenticate(token);
authenticate.getAuthorities().forEach((ag) -> System.out.println(ag.getAuthority()));
}
// 输出:ROLE_system ROLE_users
Spring中基础过滤器介绍
- OncePerRequestFilter:在一次请求中只执行一次过滤,通过设置request中Attribute属性完成
- CharacterEncodingFilter:为请求指定字符编码
- FormContentFilter:对于PUT DELETE PATCH的表单请求,将数据保存在request中
- RequestContextFilter:将请求和请求中的locale国际化处理放入RequestContextHolder和LocaleContextHolder中(线程特有)
默认加载的配置类及过滤器
if (!disableDefaults) {
// @formatter:off
http
.csrf().and()
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
.sessionManagement().and()
.securityContext().and()
.requestCache().and()
.anonymous().and()
.servletApi().and()
.apply(new DefaultLoginPageConfigurer<>()).and()
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
http.csrf()
方法添加CsrfConfigurer:预防跨站伪造攻击,按照请求方法匹配,默认忽略(GET、OPTION、TRACE和HEAD)请求
CsrfTokenRepository:存放CsrfToken令牌的仓库
CsrfFilter:跨站伪造攻击过滤器;1.获得csrf令牌(CsrfTokenRepository) 2.判断请求是否匹配 3.从请求头或参数中获取请求的令牌- WebAsyncManagerIntegrationFilter过滤器:用于集成SecurityContext到Spring异步执行机制中的WebAsyncManager
http.exceptionHandling()
添加ExceptionHandlingConfigurer:向应用程序添加Spring安全相关异常的异常处理
ExceptionTranslationFilter:对执行过滤过程中抛出的异常统一处理http.headers()
添加HeadersConfigurer:将Security相关的头部添加到response中
HeaderWriterFilter:过滤链执行完或下一个过滤器执行前添加头部http.sessionManagement()
添加SessionManagementConfigurer:允许配置会话管理
SessionManagementFilter:固定保护机制或检查多个并发登录http.securityContext()
添加SecurityContextConfigurer:为每个请求持久化SecurityContext
SecurityContextPersistenceFilter:1.从Session中获取SecurityContext不存在则创建一个新的 2.将SecurityContext交给SecurityContextHolder全局使用http.requestCache()
添加RequestCacheConfigurer:为spring security添加请求缓存
RequestCacheAwareFilter:如果缓存了一个请求并与当前请求匹配,则负责重新构建保存的请求。http.anonymous()
添加AnonymousConfigurer:为HttpSecurity配置匿名身份验证
AnonymousAuthenticationFilter:如果在SecurityContextHolder中没有Authentication则默认填充一个匿名的令牌http.servletApi()
添加ServletApiConfigurer:对request进行封装
SecurityContextHolderAwareRequestFilter:对request进行封装,使其能够访问Servlet api信息相关接口- 添加DefaultLoginPageConfigurer:未指定登录页,则该筛选器将生成登录页。
DefaultLoginPageGeneratingFilter:
DefaultLogoutPageGeneratingFilter:http.logout()
添加LogoutConfigurer:添加退出登陆支持
LogoutFilter:退出登陆操作,处理Authentication
授权和登录配置
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
12.
http.authorizeRequests()
添加ExpressionUrlAuthorizationConfigurer:为多组RequestMatcher配置不同的权限属性
ExpressionInterceptUrlRegistry:url与权限的映射管理
FilterSecurityInterceptor:是一个方法级的权限过滤器
13.http.formLogin()
添加FormLoginConfigurer:添加基于表单的身份验证
UsernamePasswordAuthenticationFilter:对/login的post方法进行身份认证
14.http.httpBasic()
添加HttpBasicConfigurer:添加基于HTTP基本身份验证
BasicAuthenticationFilter:处理HTTP请求头中包含认证信息的情况