赞
踩
WebSecurity是spring-security整个体系里面最为重要的一个安全类,通过之前的文章分析,我们可以得知spring-security是通过一个名称为springSecurityFilterChain的过滤器对所有的请求进行过滤的,同时在WebSecurityConfiguration源码分析中我们可以得知这个过滤器是通过以下方式被WebSecurity构建出来的
1 2 3 4 5 6 7 8 9 10 11 12 | @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) public Filter springSecurityFilterChain() throws Exception { boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty(); if (!hasConfigurers) { WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor .postProcess(new WebSecurityConfigurerAdapter() { }); webSecurity.apply(adapter); } return webSecurity.build(); } |
本章主要分析WebSecurity构建SpringSecurityFilterChain的流程,围绕WebSecurity的build方法展开。
在开始分析WebSecurity前,有一个很重的概念我们需要先了解一下:过滤器是被SecurityBuilder构建出来的,而SecurityConfigurer是用来配置SecurityBuilder内部的一些属性的。暂时我们可能不太明白这句话是什么意思,我们现在只需要记住这个结论就行了。
1 2 3 4 5 6 7 8 9 10 11 | // 返现参数O代表构建的对象类型,B代表builder类型,很显然就是SecurityBuilder的子类型 public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> { // 初始化SecurityBuilder,在这个方法中只应该修改builder的共享状态 // 从文档的注释上作者提醒只应该更改builder的构建状态,但实际上我在 // 很多的SecurityConfigurer实现类上发现它们都修改了builder属性,这很奇怪 void init(B builder) throws Exception; // 配置builder的属性 void configure(B builder) throws Exception; } |
1 2 3 4 5 | public interface SecurityBuilder<O> { // 构建安全对象 O build() throws Exception; } |
先来看一下WebSecurity的类图
WebSecurity继承了AbstractConfiguredSecurityBuilder实现了SecurityBuilder和ApplicationContextAware接口,咋一看好像很复杂,Builder,Configurer,Aware这些显眼的关键字,处处体现了设计模式。不要慌,一步一步分析,我们先来看它的父类AbstractConfiguredSecurityBuilder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | // 泛型O代表的是builder构建的对象,B代表builder public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>> extends AbstractSecurityBuilder<O> { private final Log logger = LogFactory.getLog(getClass()); // 所有builder的Configurer private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>>(); // 所有正在初始化的Configurer private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing = new ArrayList<SecurityConfigurer<O, B>>(); // 共享的对象 private final Map<Class<? extends Object>, Object> sharedObjects = new HashMap<Class<? extends Object>, Object>(); // 是否允许同样类型的Configurer,默认为false private final boolean allowConfigurersOfSameType; // 构建状态 private BuildState buildState = BuildState.UNBUILT; private ObjectPostProcessor<Object> objectPostProcessor; // 构造函数,默认不允许同样类型的Configurer protected AbstractConfiguredSecurityBuilder( ObjectPostProcessor<Object> objectPostProcessor) { this(objectPostProcessor, false); } protected AbstractConfiguredSecurityBuilder( ObjectPostProcessor<Object> objectPostProcessor, boolean allowConfigurersOfSameType) { Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); this.objectPostProcessor = objectPostProcessor; this.allowConfigurersOfSameType = allowConfigurersOfSameType; } // 如果当前对象还没有构建则进行构建否则返回已经构建的对象 public O getOrBuild() { if (isUnbuilt()) { try { return build(); } catch (Exception e) { logger.debug("Failed to perform build. Returning null", e); return null; } } else { return getObject(); } } // 将SecurityConfigurerAdapter应用到builder中,因为allowConfigurersOfSameType默认为false // 所以其实本质上是覆盖先前所有已经应用的SecurityConfigurer,同时设置 // SecurityConfigurerAdapter的builder @SuppressWarnings("unchecked") public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception { configurer.addObjectPostProcessor(objectPostProcessor); configurer.setBuilder((B) this); add(configurer); return configurer; } // 将SecurityConfigurer应用到builder中,因为allowConfigurersOfSameType默认为false // 所以其实本质上是覆盖先前所有已经应用的SecurityConfigurer,和上面的方法差不多 public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception { add(configurer); return configurer; } @SuppressWarnings("unchecked") public <C> void setSharedObject(Class<C> sharedType, C object) { this.sharedObjects.put(sharedType, object); } @SuppressWarnings("unchecked") public <C> C getSharedObject(Class<C> sharedType) { return (C) this.sharedObjects.get(sharedType); } public Map<Class<? extends Object>, Object> getSharedObjects() { return Collections.unmodifiableMap(this.sharedObjects); } // 添加SecurityConfigurer @SuppressWarnings("unchecked") private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception { Assert.notNull(configurer, "configurer cannot be null"); // 获取将要添加的SecurityConfigurer的class Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer .getClass(); // 同步已有的所有SecurityConfigurer synchronized (configurers) { if (buildState.isConfigured()) { throw new IllegalStateException("Cannot apply " + configurer + " to already built object"); } // 是否允许配置多个SecurityConfigurer,默认是不允许的 List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers .get(clazz) : null; if (configs == null) { configs = new ArrayList<SecurityConfigurer<O, B>>(1); } // 将SecurityConfigurer添加到list中 configs.add(configurer); // 将SecurityConfigurer重新设置回去 this.configurers.put(clazz, configs); if (buildState.isInitializing()) { this.configurersAddedInInitializing.add(configurer); } } } // 返回所有某种类型的SecurityConfigurer @SuppressWarnings("unchecked") public <C extends SecurityConfigurer<O, B>> List<C> getConfigurers(Class<C> clazz) { List<C> configs = (List<C>) this.configurers.get(clazz); if (configs == null) { return new ArrayList<>(); } return new ArrayList<>(configs); } // 移除某种类型的SecurityConfigurer @SuppressWarnings("unchecked") public <C extends SecurityConfigurer<O, B>> List<C> removeConfigurers(Class<C> clazz) { List<C> configs = (List<C>) this.configurers.remove(clazz); if (configs == null) { return new ArrayList<>(); } return new ArrayList<>(configs); } // 获取单个SecurityConfigurer,由于allowConfigurersOfSameType默认为false所以返回的就是 // 唯一的那个SecurityConfigurer @SuppressWarnings("unchecked") public <C extends SecurityConfigurer<O, B>> C getConfigurer(Class<C> clazz) { List<SecurityConfigurer<O, B>> configs = this.configurers.get(clazz); if (configs == null) { return null; } if (configs.size() != 1) { throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs); } return (C) configs.get(0); } // 移除单个SecurityConfigurer @SuppressWarnings("unchecked") public <C extends SecurityConfigurer<O, B>> C removeConfigurer(Class<C> clazz) { List<SecurityConfigurer<O, B>> configs = this.configurers.remove(clazz); if (configs == null) { return null; } if (configs.size() != 1) { throw new IllegalStateException("Only one configurer expected for type " + clazz + ", but got " + configs); } return (C) configs.get(0); } @SuppressWarnings("unchecked") public O objectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) { Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); this.objectPostProcessor = objectPostProcessor; return (O) this; } protected <P> P postProcess(P object) { return this.objectPostProcessor.postProcess(object); } // 开始构建对象 @Override protected final O doBuild() throws Exception { synchronized (configurers) { buildState = BuildState.INITIALIZING; beforeInit(); init(); buildState = BuildState.CONFIGURING; beforeConfigure(); configure(); buildState = BuildState.BUILDING; O result = performBuild(); buildState = BuildState.BUILT; return result; } } // 子类可以重写这个方法以便在SecurityConfigurer初始化前处理其它逻辑 protected void beforeInit() throws Exception { } // 子类可以重写这个方法以便在SecurityConfigurer配置前处理其它逻辑 protected void beforeConfigure() throws Exception { } // 子类重写该方法,实现具体的构建逻辑 protected abstract O performBuild() throws Exception; // SecurityConfigurer开始初始化 @SuppressWarnings("unchecked") private void init() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); // SecurityConfigurer初始化,将builder对象传入 for (SecurityConfigurer<O, B> configurer : configurers) { configurer.init((B) this); } // SecurityConfigurer初始化,将builder对象传入 for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) { configurer.init((B) this); } } // SecurityConfigurer开始配置 @SuppressWarnings("unchecked") private void configure() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> configurer : configurers) { configurer.configure((B) this); } } private Collection<SecurityConfigurer<O, B>> getConfigurers() { List<SecurityConfigurer<O, B>> result = new ArrayList<SecurityConfigurer<O, B>>(); for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) { result.addAll(configs); } return result; } private boolean isUnbuilt() { synchronized (configurers) { return buildState == BuildState.UNBUILT; } } private static enum BuildState { UNBUILT(0), INITIALIZING(1), CONFIGURING(2), BUILDING(3), BUILT(4); private final int order; BuildState(int order) { this.order = order; } public boolean isInitializing() { return INITIALIZING.order == order; } public boolean isConfigured() { return order >= CONFIGURING.order; } } } |
AbstractConfiguredSecurityBuilder可以理解为它是一个能够被配置的SecurityBuilder基类,能够给它配置一些SecurityConfigurer,这些SecurityConfigurer能够对AbstractConfiguredSecurityBuilder进行配置,最终进行build后构建出来的对象(FilterChainProxy)就拥有了SecurityConfigurer配置的功能。同时它又继承了AbstractSecurityBuilder,保证构建的对象只构建一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> { private AtomicBoolean building = new AtomicBoolean(); private O object; // 进行构建对象时保证对象没有构建才调用doBuild方法进行构建 public final O build() throws Exception { if (this.building.compareAndSet(false, true)) { this.object = doBuild(); return this.object; } throw new AlreadyBuiltException("This object has already been built"); } // 获取被构建的对象,如果该对象还没有构建就抛出异常 public final O getObject() { if (!this.building.get()) { throw new IllegalStateException("This object has not been built"); } return this.object; } // 子类实现该方法进行具体的构建逻辑 protected abstract O doBuild() throws Exception; } |
AbstractSecurityBuilder保证对象在进行构建的时候只构建一次,是通过原子类AtomicBoolean保证的。接下来我们分析一下WebSecurity的源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter>, ApplicationContextAware { private final Log logger = LogFactory.getLog(getClass()); // 在整个web请求中需要忽略的请求 private final List<RequestMatcher> ignoredRequests = new ArrayList<>(); // 一些列的SecurityBuilder,从泛型参数可以看出最终每一个SecurityBuilder构建出来的 // 对象就是SecurityFilterChain private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<SecurityBuilder<? extends SecurityFilterChain>>(); // 需要忽略的请求的RequestMatcher的Configurer,有点绕口。。。 private IgnoredRequestConfigurer ignoredRequestRegistry; // 熟悉的FilterSecurityInterceptor private FilterSecurityInterceptor filterSecurityInterceptor; // http防火墙,在过滤器链执行器调用,主要是用来做一些安全的防护 private HttpFirewall httpFirewall; private boolean debugEnabled; private WebInvocationPrivilegeEvaluator privilegeEvaluator; private DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); // 熟悉的FilterInvocation private SecurityExpressionHandler<FilterInvocation> expressionHandler = defaultWebSecurityExpressionHandler; // 用来设置FilterSecurityInterceptor的,会在构建完成后调用该方法 private Runnable postBuildAction = new Runnable() { public void run() { } }; public WebSecurity(ObjectPostProcessor<Object> objectPostProcessor) { super(objectPostProcessor); } // 在整个web请求中需要忽略的请求的RequestMatcher的Configurer public IgnoredRequestConfigurer ignoring() { return ignoredRequestRegistry; } // 自定义HttpFirewall,默认的实现是StrictHttpFirewall public WebSecurity httpFirewall(HttpFirewall httpFirewall) { this.httpFirewall = httpFirewall; return this; } public WebSecurity debug(boolean debugEnabled) { this.debugEnabled = debugEnabled; return this; } // 添加构建器以创建SecurityFilterChain实例,该方法一般是在 // WebSecurityConfigurerAdapter#init(WebSecurity)处被调用 public WebSecurity addSecurityFilterChainBuilder( SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder) { this.securityFilterChainBuilders.add(securityFilterChainBuilder); return this; } public WebSecurity privilegeEvaluator( WebInvocationPrivilegeEvaluator privilegeEvaluator) { this.privilegeEvaluator = privilegeEvaluator; return this; } public WebSecurity expressionHandler( SecurityExpressionHandler<FilterInvocation> expressionHandler) { Assert.notNull(expressionHandler, "expressionHandler cannot be null"); this.expressionHandler = expressionHandler; return this; } public SecurityExpressionHandler<FilterInvocation> getExpressionHandler() { return expressionHandler; } public WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() { if (privilegeEvaluator != null) { return privilegeEvaluator; } return filterSecurityInterceptor == null ? null : new DefaultWebInvocationPrivilegeEvaluator(filterSecurityInterceptor); } public WebSecurity securityInterceptor(FilterSecurityInterceptor securityInterceptor) { this.filterSecurityInterceptor = securityInterceptor; return this; } public WebSecurity postBuildAction(Runnable postBuildAction) { this.postBuildAction = postBuildAction; return this; } // 最终的构建逻辑 @Override protected 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"); // 过滤器链数为需要忽略的请求数加上已经配置的builder数 int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size(); List<SecurityFilterChain> securityFilterChains = new ArrayList<>( chainSize); // 每一个忽略的请求对应的过滤器链是DefaultSecurityFilterChain for (RequestMatcher ignoredRequest : ignoredRequests) { securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest)); } // 已配置的securityFilterChainBuilder构建相应的过滤器链 for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) { securityFilterChains.add(securityFilterChainBuilder.build()); } // 很重要,这就是最终的过滤器,将所有的过滤器链包含在里面了!!! FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains); if (httpFirewall != null) { filterChainProxy.setFirewall(httpFirewall); } filterChainProxy.afterPropertiesSet(); Filter result = filterChainProxy; if (debugEnabled) { logger.warn("\n\n" + "********************************************************************\n" + "********** Security debugging is enabled. *************\n" + "********** This may include sensitive information. *************\n" + "********** Do not use in a production system! *************\n" + "********************************************************************\n\n"); result = new DebugFilter(filterChainProxy); } postBuildAction.run(); return result; } public final class MvcMatchersIgnoredRequestConfigurer extends IgnoredRequestConfigurer { private final List<MvcRequestMatcher> mvcMatchers; private MvcMatchersIgnoredRequestConfigurer(ApplicationContext context, List<MvcRequestMatcher> mvcMatchers) { super(context); this.mvcMatchers = mvcMatchers; } public IgnoredRequestConfigurer servletPath(String servletPath) { for (MvcRequestMatcher matcher : this.mvcMatchers) { matcher.setServletPath(servletPath); } return this; } } public class IgnoredRequestConfigurer extends AbstractRequestMatcherRegistry<IgnoredRequestConfigurer> { private IgnoredRequestConfigurer(ApplicationContext context) { setApplicationContext(context); } @Override public MvcMatchersIgnoredRequestConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) { List<MvcRequestMatcher> mvcMatchers = createMvcMatchers(method, mvcPatterns); WebSecurity.this.ignoredRequests.addAll(mvcMatchers); return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), mvcMatchers); } @Override public MvcMatchersIgnoredRequestConfigurer mvcMatchers(String... mvcPatterns) { return mvcMatchers(null, mvcPatterns); } @Override protected IgnoredRequestConfigurer chainRequestMatchers( List<RequestMatcher> requestMatchers) { WebSecurity.this.ignoredRequests.addAll(requestMatchers); return this; } /** * Returns the {@link WebSecurity} to be returned for chaining. */ public WebSecurity and() { return WebSecurity.this; } } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.defaultWebSecurityExpressionHandler .setApplicationContext(applicationContext); try { this.defaultWebSecurityExpressionHandler.setPermissionEvaluator(applicationContext.getBean( PermissionEvaluator.class)); } catch(NoSuchBeanDefinitionException e) {} this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext); try { this.httpFirewall = applicationContext.getBean(HttpFirewall.class); } catch(NoSuchBeanDefinitionException e) {} } } |
分析到这,我们对WebSecurity就已经有一个大概的了解了,下面对它进行一个总结
分析到这,其实还有一个地方没有搞明白,我们现在知道WebSecurity内的SecurityBuilder构建了SecurityFilterChain,最终将这些SecurityFilterChain包装成一个FilterChainProxy,但是WebSecurity内的那些SecurityBuilder是什么时候配置的呢?通过debug发现其实它是在AbstractConfiguredSecurityBuilder类中的init方法配置的
1 2 3 4 5 6 7 8 9 10 11 | private void init() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); // SecurityBuilder就是在这个时候添加的 for (SecurityConfigurer<O, B> configurer : configurers) { configurer.init((B) this); } for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) { configurer.init((B) this); } } |
既然是在这个地方配置的那么这个SecurityConfigurer和SecurityBuilder又是什么呢?这里直接给出结果:WebSecurity内维护的SecurityBuilder是通过调用WebSecurityConfigurerAdapter的init方法添加的,最终的添加的SecurityBuilder就是HttpSecurity。结果其实不意外,平常我们在配置spring-security的时候通常就是继承WebSecurityConfigurerAdapter类然后调用configure(HttpSecurity http)方法进行配置的。这里就又引出了WebSecurityConfigurerAdapter和HttpSecurity类,篇幅有限,下一章我们再继续分析它是如何配置这个HttpSecurity的。
WebSecurity通过内部维护的SecurityBuilder列表生成的多个SpringSecurityFilterChain,然后再将这多个SpringSecurityFilterChain包装成FilterChainProxy,所以最终配置的这个过滤器对象是一个包含了多个SpringSecurityFilterChain的过滤器。下面用一张图来总结WebSecurity构建过滤器的流程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。