javascript
Spring Security源码解析(二)——引入
目錄
Spring Security的引入
AuthenticationConfiguration
WebSecurityConfiguration
引入?FilterChain。
設置FilterChain的配置信息。
?
?WebSecurity
AbstractConfiguredSecurityBuilder
屬性
doBuild()方法
WebSecurity
屬性
?performBuild()
WebSecurityConfigurerAdapter
類圖
屬性
init()方法
configure()方法
getHttp()方法
HttpSecurity
類圖
?HttpSecurityBuilder
HttpSecurity
屬性
構造函數
performBuild
AuthenticationManagerBuilder配置。
https://github.com/spring-cloud/spring-cloud-security/tree/v2.2.1.RELEASE
?
Spring Security的引入
在使用Spring Security時,會定義一個WebSecurityConfigurerAdapter的子類,并同時加上注解@EnableWebSecurity。
// org.springframework.security.config.annotation.web.configuration; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter@EnableWebSecurity用于引入security功能,WebSecurityConfigurerAdapter實現類用于擴展功能。
@Import({ WebSecurityConfiguration.class,SpringWebMvcImportSelector.class,OAuth2ImportSelector.class }) @EnableGlobalAuthentication @Configuration public @interface EnableWebSecurity {/*** Controls debugging support for Spring Security. Default is false.* @return if true, enables debug support with Spring Security*/boolean debug() default false; }@EnableWebSecurity又會引入@EnableGlobalAuthentication
@Import(AuthenticationConfiguration.class) @Configuration public @interface EnableGlobalAuthentication { }因此會導入幾個類:
- AuthenticationConfiguration。
- WebSecurityConfiguration。引入FilterChain。
- SpringWebMvcImportSelector。判斷是否引入了Spring MVC。
- OAuth2ImportSelector。判斷是否引入了OAuth2。
AuthenticationConfiguration
@Import(ObjectPostProcessorConfiguration.class) public class AuthenticationConfiguration {@Beanpublic AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context) {LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, AuthenticationEventPublisher.class);DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder);if (authenticationEventPublisher != null) {result.authenticationEventPublisher(authenticationEventPublisher);}return result;}@Beanpublic static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {return new EnableGlobalAuthenticationAutowiredConfigurer(context);}@Beanpublic static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {return new InitializeUserDetailsBeanManagerConfigurer(context);}@Beanpublic static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {return new InitializeAuthenticationProviderBeanManagerConfigurer(context);}}WebSecurityConfiguration
引入?FilterChain。
創建名稱為springSecurityFilterChain的Filter?
//public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain"; @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)public Filter springSecurityFilterChain() throws Exception { //判斷是否自定義了SecurityConfigurerboolean hasConfigurers = webSecurityConfigurers != null&& !webSecurityConfigurers.isEmpty();if (!hasConfigurers) { //如果沒有自定義,則使用默認的。WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {});webSecurity.apply(adapter);} //builder 返回一個Filterreturn webSecurity.build();}設置FilterChain的配置信息。
創建了一個WebSecurity。
@Autowired(required = false)public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)throws Exception { //創建webSecurity webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));if (debugEnabled != null) {webSecurity.debug(debugEnabled);} //webSecurityConfigurers排序。通過@Order注解。webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);//對Order進行比較是否有相同的(保證不相同),由于前面進行了排序,只要比較前后有相同的就可以Integer previousOrder = null;Object previousConfig = null;for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {Integer order = AnnotationAwareOrderComparator.lookupOrder(config);if (previousOrder != null && previousOrder.equals(order)) {throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of "+ order + " was already used on " + previousConfig + ", so it cannot be used on "+ config + " too.");}previousOrder = order;previousConfig = config;}for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) { //webSecurity 應用配置。webSecurity.apply(webSecurityConfigurer);}this.webSecurityConfigurers = webSecurityConfigurers;}獲取configurers。一般返回的就是自定義的WebSecurityConfigurer。
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<>(); //獲取所有WebSecurityConfigurer的實現類。Map<String, WebSecurityConfigurer> beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class);for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {webSecurityConfigurers.add(entry.getValue());}return webSecurityConfigurers;}?
?WebSecurity
Filter的創建,最終是通過WebSecurity的實例的build()方法實現。
WebSecurity的類繼承如下圖:
- SecurityBuilder定義了構建的接口標準
- AbstractSecurityBuilder實現build方法,用AtomicBoolean的變量building保證多線程情況下,操作的原子性。此處采用的是模板模式。定義了doBuild()抽象方法
- AbstractConfiguredSecurityBuilder 繼承AbstractSecurityBuilder實現doBuild()方法,也采用模板模式,定義了實現的具體的步驟。
AbstractConfiguredSecurityBuilder
屬性
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>extends AbstractSecurityBuilder<O> {//SecurityConfigurer 列表。private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing = new ArrayList<>();private final Map<Class<?>, Object> sharedObjects = new HashMap<>();private final boolean allowConfigurersOfSameType; //當前狀態。private BuildState buildState = BuildState.UNBUILT;private ObjectPostProcessor<Object> objectPostProcessor; }doBuild()方法
doBuild()方法的步驟:
?
private Collection<SecurityConfigurer<O, B>> getConfigurers() {List<SecurityConfigurer<O, B>> result = new ArrayList<>();for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {result.addAll(configs);}return result;}init()方法
private void init() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();//循環所有的configurer ,調用其初始化。for (SecurityConfigurer<O, B> configurer : configurers) {configurer.init((B) this);}for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {configurer.init((B) this);}}configure()方法
private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); //循環調用configurer 的configure()方法。for (SecurityConfigurer<O, B> configurer : configurers) {configurer.configure((B) this);}}apply()方法
apply方法用于設置SecurityConfigurer的屬性,并加入到此builder的configurers中。
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception {configurer.addObjectPostProcessor(objectPostProcessor);configurer.setBuilder((B) this);add(configurer);return configurer;}public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {add(configurer);return configurer;}WebSecurity
屬性
//忽略權限控制的請求 Matcher。 private final List<RequestMatcher> ignoredRequests = new ArrayList<>(); //構造SecurityFilterChain 的Buidler列表。private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<>();private IgnoredRequestConfigurer ignoredRequestRegistry;private FilterSecurityInterceptor filterSecurityInterceptor;private HttpFirewall httpFirewall;private boolean debugEnabled;private WebInvocationPrivilegeEvaluator privilegeEvaluator;private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();private SecurityExpressionHandler<FilterInvocation> expressionHandler = defaultWebSecurityExpressionHandler;private Runnable postBuildAction = () -> {};?performBuild()
真實構造FilterChain:FilterChainProxy?
@Overrideprotected Filter performBuild() throws Exception {Assert.state(!securityFilterChainBuilders.isEmpty(),() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "+ "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "+ "More advanced users can invoke "+ WebSecurity.class.getSimpleName()+ ".addSecurityFilterChainBuilder directly");int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();//securityFilterChainsList<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);//如果是ignoredRequest類型的,那么久添加默認過濾器鏈(DefaultSecurityFilterChain) for (RequestMatcher ignoredRequest : ignoredRequests) {securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));}//如果是securityFilterChainBuilder類型的,那么通過securityFilterChainBuilder的build()方法來構建過濾器鏈for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {securityFilterChains.add(securityFilterChainBuilder.build());}//將過濾器鏈交給一個過濾器鏈代理對象,此代理對象里面存儲的是所有FilterChain。FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (httpFirewall != null) {filterChainProxy.setFirewall(httpFirewall);}filterChainProxy.afterPropertiesSet();Filter result = filterChainProxy;if (debugEnabled) {result = new DebugFilter(filterChainProxy);}//構造完后處理。postBuildAction.run();return result;}WebSecurityConfigurerAdapter
類圖
?
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {void init(B builder) throws Exception;void configure(B builder) throws Exception; }?WebSecurityConfigurer構造的是Filter的實例。
public interface WebSecurityConfigurer<T extends SecurityBuilder<Filter>> extendsSecurityConfigurer<Filter, T> {}屬性
使用WebSecurity作為Filter的builder。
@Order(100) public abstract class WebSecurityConfigurerAdapter implementsWebSecurityConfigurer<WebSecurity> {private ApplicationContext context;private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();private ObjectPostProcessor<Object> objectPostProcessor = new ObjectPostProcessor<Object>() {public <T> T postProcess(T object) {throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration");}};private AuthenticationConfiguration authenticationConfiguration;private AuthenticationManagerBuilder authenticationBuilder;private AuthenticationManagerBuilder localConfigureAuthenticationBldr;private boolean disableLocalConfigureAuthenticationBldr;private boolean authenticationManagerInitialized;private AuthenticationManager authenticationManager;private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();private HttpSecurity http; //是否可使用默認值。private boolean disableDefaults;init()方法
通過getHttp()方法構造HttpSecurity,并設置為WebSecurity的builder。
public void init(final WebSecurity web) throws Exception { //構造 HttpSecurity final HttpSecurity http = getHttp(); //添加chain builder,類型為SecurityBuilder<? extends SecurityFilterChain>。web.addSecurityFilterChainBuilder(http) .postBuildAction(() -> {FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);web.securityInterceptor(securityInterceptor);});}configure()方法
空實現。子類可覆蓋。
public void configure(WebSecurity web) throws Exception {}getHttp()方法
protected final HttpSecurity getHttp() throws Exception {if (http != null) {return http;} //S1:DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher); //S2:AuthenticationManager authenticationManager = authenticationManager();authenticationBuilder.parentAuthenticationManager(authenticationManager);authenticationBuilder.authenticationEventPublisher(eventPublisher);Map<Class<?>, Object> sharedObjects = createSharedObjects(); //S3:http = new HttpSecurity(objectPostProcessor, authenticationBuilder,sharedObjects);if (!disableDefaults) { //S4:// @formatter:offhttp.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:onClassLoader classLoader = this.context.getClassLoader(); //加載所有的AbstractHttpConfigurer子類。并應用apply方法。List<AbstractHttpConfigurer> defaultHttpConfigurers =SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {http.apply(configurer);}} //S5:configure(http);return http;}步驟:
S1:
S2:構造AuthenticationManager 。
S3:構造HttpSecurity。
S4:如果不禁用默認值,則使用默認configurer設置HttpSecurity。
S5:配置HttpSecurity
?
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();}HttpSecurity
HttpSecurity是一個Builder,用于構造FilterChain。
類圖
?HttpSecurityBuilder
用于構造DefaultSecurityFilterChain。可維護Builder的屬性。提供了設置 用于認證的bean的方法。
public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extendsSecurityBuilder<DefaultSecurityFilterChain> {<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C getConfigurer(Class<C> clazz);<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C removeConfigurer(Class<C> clazz);<C> void setSharedObject(Class<C> sharedType, C object);<C> C getSharedObject(Class<C> sharedType);H authenticationProvider(AuthenticationProvider authenticationProvider);H userDetailsService(UserDetailsService userDetailsService) throws Exception;H addFilterAfter(Filter filter, Class<? extends Filter> afterFilter);H addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter);H addFilter(Filter filter); }HttpSecurity
屬性
//請求匹配過濾的配置信息 private final RequestMatcherConfigurer requestMatcherConfigurer; //過濾器列表private List<Filter> filters = new ArrayList<>(); //匹配任何請求的匹配器private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE; //過濾器比較。private FilterComparator comparator = new FilterComparator();?FilterComparator?
用于Filter排序。并定義了常用Filter的Order順序。初始值100,步長100。可以通過 方法在某個Filter前面后者后面加Filter。
final class FilterComparator implements Comparator<Filter>, Serializable {public int compare(Filter lhs, Filter rhs) {Integer left = getOrder(lhs.getClass());Integer right = getOrder(rhs.getClass());return left - right;} }?
private static final int INITIAL_ORDER = 100;private static final int ORDER_STEP = 100; FilterComparator() {Step order = new Step(INITIAL_ORDER, ORDER_STEP);put(ChannelProcessingFilter.class, order.next());put(ConcurrentSessionFilter.class, order.next());put(WebAsyncManagerIntegrationFilter.class, order.next());put(SecurityContextPersistenceFilter.class, order.next());put(HeaderWriterFilter.class, order.next()); ... ...?
private final Map<String, Integer> filterToOrder = new HashMap<>();public void registerAfter(Class<? extends Filter> filter,Class<? extends Filter> afterFilter) {Integer position = getOrder(afterFilter);if (position == null) {throw new IllegalArgumentException("Cannot register after unregistered Filter " + afterFilter);}put(filter, position + 1);}?
?RequestMatcher?
用于判斷request是否匹配,并返回匹配結果。
public interface RequestMatcher {boolean matches(HttpServletRequest request);default MatchResult matcher(HttpServletRequest request) {boolean match = matches(request);return new MatchResult(match, Collections.emptyMap());}class MatchResult {private final boolean match;private final Map<String, String> variables;MatchResult(boolean match, Map<String, String> variables) {this.match = match;this.variables = variables;} }}?默認實現了很多個RequestMatcher。
?
public final class AnyRequestMatcher implements RequestMatcher {public static final RequestMatcher INSTANCE = new AnyRequestMatcher();public boolean matches(HttpServletRequest request) {return true;} }public final class AndRequestMatcher implements RequestMatcher {private final List<RequestMatcher> requestMatchers;public AndRequestMatcher(List<RequestMatcher> requestMatchers) { ... ... this.requestMatchers = requestMatchers;}public AndRequestMatcher(RequestMatcher... requestMatchers) {this(Arrays.asList(requestMatchers));}public boolean matches(HttpServletRequest request) {for (RequestMatcher matcher : requestMatchers) {if (logger.isDebugEnabled()) {logger.debug("Trying to match using " + matcher);}if (!matcher.matches(request)) {logger.debug("Did not match");return false;}}return true;} }?
構造函數
構造函數,保存了AuthenticationManagerBuilder實例,并保存了一些共用對象。
public HttpSecurity(ObjectPostProcessor<Object> objectPostProcessor,AuthenticationManagerBuilder authenticationBuilder,Map<Class<?>, Object> sharedObjects) {super(objectPostProcessor);Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null");setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder);for (Map.Entry<Class<?>, Object> entry : sharedObjects.entrySet()) {setSharedObject((Class<Object>) entry.getKey(), entry.getValue());}ApplicationContext context = (ApplicationContext) sharedObjects.get(ApplicationContext.class);this.requestMatcherConfigurer = new RequestMatcherConfigurer(context);}performBuild
@Overrideprotected DefaultSecurityFilterChain performBuild() { //排序filters.sort(comparator); //構造DefaultSecurityFilterChain。會在每個configurer的configure()方法中,把filter加入到Filtersreturn new DefaultSecurityFilterChain(requestMatcher, filters);}?Filters通過addFilter 添加。
public HttpSecurity addFilter(Filter filter) {Class<? extends Filter> filterClass = filter.getClass();if (!comparator.isRegistered(filterClass)) {throw new IllegalArgumentException("The Filter class "+ filterClass.getName()+ " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");}this.filters.add(filter);return this;}AuthenticationManagerBuilder配置。
為AuthenticationManagerBuilder 配置AuthenticationProvider ,UserDetailsService?
public HttpSecurity authenticationProvider(AuthenticationProvider authenticationProvider) {getAuthenticationRegistry().authenticationProvider(authenticationProvider);return this;}/** (non-Javadoc)** @see* org.springframework.security.config.annotation.web.HttpSecurityBuilder#userDetailsService* (org.springframework.security.core.userdetails.UserDetailsService)*/public HttpSecurity userDetailsService(UserDetailsService userDetailsService)throws Exception {getAuthenticationRegistry().userDetailsService(userDetailsService);return this;}private AuthenticationManagerBuilder getAuthenticationRegistry() {return getSharedObject(AuthenticationManagerBuilder.class);}FilterChainProxy生成時序圖
?
?
總結
以上是生活随笔為你收集整理的Spring Security源码解析(二)——引入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Security源码解析(
- 下一篇: Spring Security源码解析(