您的位置:首页 > 教育 > 锐评 > Spring Security

Spring Security

2024/10/6 12:21:27 来源:https://blog.csdn.net/qq_36851469/article/details/141887420  浏览:    关键词:Spring Security

Spring Security框架‌的主要作用是为基于Spring的企业应用系统提供声明式的安全访问控制解决方案。它是一个开源项目,旨在为Java应用程序提供强大和灵活的安全性解决方案,包括认证、授权、防护等多个方面。

认证与授权:Spring Security支持多种认证机制,如表单登录、HTTP基本认证、OAuth2、OpenID等,以及基于角色或权限的访问控制,提供细粒度的访问控制。

安全防护:提供多种防护措施,如防止会话固定攻击、点击劫持、跨站请求伪造等攻击,保护应用免受安全威胁。

集成性:与Spring框架以及其他第三方库和框架进行无缝集成,如Spring MVC、Thymeleaf、Hibernate等,便于开发者在已有的技术栈中快速集成安全功能。

其他功能:还包括单点登录(SSO)功能,可以将多个应用程序集成到一个中央身份验证系统中,提供可定制的集成与其他Spring框架,如Spring MVC和Spring Boot。

SecurityFilterChain:SecurityFilterChain是Spring Security的核心组件之一,负责处理所有的HTTP请求。它由一系列的过滤器组成,这些过滤器在请求处理的不同阶段执行安全检查。

AuthenticationManager:身份验证的核心接口,负责验证用户的凭证。它会调用相应的AuthenticationProvider来实现具体的验证逻辑。

UserDetailsService:加载用户的特定数据。通过实现该接口,可以从数据库或其他数据源中获取用户信息。

SecurityContext:SecurityContext用于存储用户的身份信息(Authentication对象),它包含了用户的权限和角色信息,允许应用程序在整个请求周期内访问该信息。

工作流程:

  1. 客户端发送请求到服务器。
  2. SecurityFilterChain拦截请求,并检查用户的身份信息。
  3. 如果用户未认证,跳转到登录页面。
  4. 用户提交凭证,经过AuthenticationManager进行身份验证。
  5. 验证成功后,用户的身份信息被存储在SecurityContext中。
  6. 根据用户的角色和权限,决定是否允许访问请求的资源。

简单总结 Spring Security 流程即为:构建 Filter 链、执行Filter 链。Filter 链的构建依赖用户显式创建 SecurityFilterChain 实例,最后被 WebSecurityConfiguration 包装为FilterChainProxy。


1.@EnableWebSecurity

该注解是通过类SecurityAutoConfiguration间接引入的。

该注解引入类WebSecurityConfiguration、SpringWebMvcImportSelector、HttpSecurityConfiguration、OAuth2ImportSelector。

类WebSecurityConfiguration负责提供Spring Security框架存在的11个Filter。

类HttpSecurityConfiguration负责实例化HttpSecurity实例。


2.WebSecurityConfiguration

如下伪代码所示WebSecurityConfiguration核心功能就是完成Filter实例的创建。

public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {private WebSecurity webSecurity;private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;private List<SecurityFilterChain> securityFilterChains = Collections.emptyList();@Autowired(required = false)private HttpSecurity httpSecurity;@Autowired(required = false)void setFilterChains(List<SecurityFilterChain> securityFilterChains) {this.securityFilterChains = securityFilterChains;}@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)public Filter springSecurityFilterChain() throws Exception {...for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);}for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {customizer.customize(this.webSecurity);}return this.webSecurity.build();}@Autowired(required = false)void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {this.webSecurityCustomizers = webSecurityCustomizers;}
}

但是必须借助SecurityFilterChain才能实现,最终被IOC容器管理的过滤器类型为FilterChainProxy

public class FilterChainProxy extends GenericFilterBean {private List<SecurityFilterChain> filterChains;public FilterChainProxy(List<SecurityFilterChain> filterChains) {this.filterChains = filterChains;}
}

web服务处理请求过程中也是在过滤器FilterChainProxy内部实现11个具体Filter依次顺序执行。


2.1.HttpSecurity

类HttpSecurityConfiguration负责实例化Scope类型为prototype的HttpSecurity实例。此时的HttpSecurity其相关属性均为默认值。


2.2.SecurityFilterChain

SecurityFilterChain实例的创建需要用户显式的通过HttpSecurity类完成。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.cors(AbstractHttpConfigurer::disable).csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(registry -> registry.requestMatchers(s).permitAll().requestMatchers(AntPathRequestMatcher.antMatcher(HttpMethod.OPTIONS)).permitAll().requestMatchers(AntPathRequestMatcher.antMatcher("/**/*")).hasRole("role_user").anyRequest().authenticated()).oauth2ResourceServer(oauth2Configurer -> oauth2Configurer.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwt -> {Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");Collection<String> roles = realmAccess.get("roles");var grantedAuthorities = roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).toList();return new JwtAuthenticationToken(jwt, grantedAuthorities);})));httpSecurity.exceptionHandling(handleConfig -> handleConfig.accessDeniedHandler(m_AccessDeniedHandler));return httpSecurity.build();
}

Security框架内部提供了唯一的实现类DefaultSecurityFilterChain。如下伪代码所示filters集合默认情况下存在11个过滤器。

public final class DefaultSecurityFilterChain implements SecurityFilterChain {private final RequestMatcher requestMatcher;private final List<Filter> filters;public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {this.requestMatcher = requestMatcher;this.filters = new ArrayList<>(filters);}
}

按照顺序分别为:DisableEncodeUrlFilter、WebAsyncManagerIntegrationFilter、SecurityContextHolderFilter、HeaderWriterFilter、LogoutFilter、BearerTokenAuthenticationFilter、RequestAttributeAuthenticationFilter、SecurityContextHolderAwareRequestFilter、AnonymousAuthenticationFilter、ExceptionTranslationFilter、AuthorizationFilter。


3.SecurityFilterChain构建标准流程

抽象类AbstractConfiguredSecurityBuilder常见的子类为HttpSecurity & WebSecurity。

类HttpSecurity内部存在两个重要字段属性:元素类型为OrderedFilter的列表集合的filters & 元素类型为SecurityConfigurer的Map集合之configurers。

public final class HttpSecurity extends AbstractConfiguredSecurityBuilder{private final RequestMatcherConfigurer requestMatcherConfigurer;private List<OrderedFilter> filters = new ArrayList<>();private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;private FilterOrderRegistration filterOrders = new FilterOrderRegistration();private AuthenticationManager authenticationManager;
}

字段filters维护的是上述所讲述的11种过滤器。

public abstract class AbstractConfiguredSecurityBuilder {private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();private final Map<Class<?>, Object> sharedObjects = new HashMap<>();
}

字段 configurers 维护的是上述所讲述的类SecurityConfigurer的子类。

类HttpSecurity的作用就是构建顺序Filter链的过程,每个Filter的具体功能被封装在SecurityConfigurer中。所以需要探明Filter的创建以及Filter与SecurityConfigurer之间的关系。

3.1.SecurityConfigurer子类创建过程

HttpSecurity构建相关功能时都会创建与之相对应的抽象类AbstractHttpConfigurer的子类,诸如此类~[cors,CorsConfigurer],[authorizeHttpRequests,AuthorizeHttpRequestsConfigurer],[oauth2ResourceServer,OAuth2ResourceServerConfigurer],...,等。

每个SecurityConfigurer子类最终都会被添加至HttpSecurity的属性configurers中。

以AuthorizeHttpRequestsConfigurer为例:该SecurityConfigurer主要是基于请求URL验证请求的合法性。

如下所示registery通常利用requestMatchers设置相关过滤条件:

//以下只是AuthorizeHttpRequestsConfigurer特有流程
.authorizeHttpRequests(registry -> registry//默认registry为AuthorizationManagerRequestMatcherRegistry.requestMatchers(s_AuthList).permitAll().requestMatchers(AntPathRequestMatcher.antMatcher(HttpMethod.OPTIONS)).permitAll().requestMatchers(AntPathRequestMatcher.antMatcher("/**/*")).hasRole("role_user").anyRequest().authenticated()
)

requestMatchers方法接受三种类型的参数:字符串数组【路径正则表达式】、RequestMatcher类型的数组以及HttpMethod。返回值类型为AuthorizedUrl

3.1.1.AuthorizedUrl

3.2.Filter创建过程

public abstract class AbstractConfiguredSecurityBuilder{protected final O doBuild() throws Exception {synchronized (this.configurers) {this.buildState = BuildState.INITIALIZING;beforeInit();// 触发重写过该init方法的SecurityConfigurer子类init();this.buildState = BuildState.CONFIGURING;beforeConfigure();// 触发重写过该configure方法的SecurityConfigurer子类,创建与当前SecurityConfigurer对应的Filterconfigure();this.buildState = BuildState.BUILDING;O result = performBuild();this.buildState = BuildState.BUILT;return result;}}
}

3.2.1.init


3.2.2. configure

以AuthorizeHttpRequestsConfigurer为例:过滤器AuthorizationFilter创建过程中默认得到的AuthorizationManager的类型为:RequestMatcherDelegatingAuthorizationManager

public final class AuthorizeHttpRequestsConfigurer{public void configure(H http) {AuthorizationManager<HttpServletRequest> authorizationManager = this.registry.createAuthorizationManager();AuthorizationFilter authorizationFilter = new AuthorizationFilter(authorizationManager);authorizationFilter.setAuthorizationEventPublisher(this.publisher);authorizationFilter.setShouldFilterAllDispatcherTypes(this.registry.shouldFilterAllDispatcherTypes);authorizationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());http.addFilter(postProcess(authorizationFilter));}	
}

4.Filter

Spring Security本质上就是顺序Filter链执行过程,在执行目标方法之前或者在Servlet架构层完成对请求的验证过程。本章节以过滤器之AuthorizationFilter为例。

4.1.AuthorizationFilter

public class AuthorizationFilter extends GenericFilterBean {public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain){HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;...AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, request, decision);if (decision != null && !decision.isGranted()) {// 当前过滤器直接拒绝请求,响应头存在:401 Unauthorized内容throw new AccessDeniedException("Access Denied");}// 通过当前过滤器,执行下一个过滤器chain.doFilter(request, response);}
}
public final class RequestMatcherDelegatingAuthorizationManager{private final List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>> mappings;public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {for (RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> mapping : this.mappings) {RequestMatcher matcher = mapping.getRequestMatcher();MatchResult matchResult = matcher.matcher(request);if (matchResult.isMatch()) {AuthorizationManager<RequestAuthorizationContext> manager = mapping.getEntry();// 返回授权决定AuthorizationDecisionreturn manager.check(authentication,new RequestAuthorizationContext(request, matchResult.getVariables()));}}return DENY;//说明当前过滤器直接拒绝当前请求}
}

通过当前过滤器的表现形式为:返回granted为true的AuthorizationDecision实例。该实例返回之前请求必须满足RequestMatcher条件 & AuthorizationManager条件。


<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-authorization-server</artifactId><version>3.3.3</version>
</dependency>

依赖spring-security-oauth2-authorization-server完全覆盖spring-boot-starter-oauth2-authorization-server。

<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-authorization-server</artifactId><version>1.3.2</version>
</dependency>

与 spring-security-oauth2-authorization-server 相比,spring-boot-starter-security依赖多了一个spring-aop的jar包依赖。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>3.3.3</version>
</dependency>

综上所述,spring-security-oauth2-authorization-server 、spring-boot-starter-security两个依赖完全提供spring-security全部功能。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com