Spring Security 及 OAuth2 中 **ConfigurerAdapter 的關(guān)系
Spring Security 及 OAuth2 中 WebSecurityConfigurerAdapter,
AuthorizationServerConfigurerAdapter繁莹,ResourceServerConfigurerAdapter 之間啥關(guān)系
安全服務(wù)配置類
@EnableWebSecurity
加載WebSecurityConfiguration
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@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;
}
WebSecurityConfiguration
由@EnableWebSecurity注解加載
@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
ObjectPostProcessor<Object> objectPostProcessor,
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
throws Exception {
webSecurity = objectPostProcessor
.postProcess(new WebSecurity(objectPostProcessor));
if (debugEnabled != null) {
webSecurity.debug(debugEnabled);
}
Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);
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.apply(webSecurityConfigurer);
}
this.webSecurityConfigurers = webSecurityConfigurers;
}
@Bean
public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
ConfigurableListableBeanFactory beanFactory) {
return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
}
}
/**
* A class used to get all the {@link WebSecurityConfigurer} instances from the current
* {@link ApplicationContext} but ignoring the parent.
*
* @author Rob Winch
*
*/
final class AutowiredWebSecurityConfigurersIgnoreParents {
private final ConfigurableListableBeanFactory beanFactory;
public AutowiredWebSecurityConfigurersIgnoreParents(
ConfigurableListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "beanFactory cannot be null");
this.beanFactory = beanFactory;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
Map<String, WebSecurityConfigurer> beansOfType = beanFactory
.getBeansOfType(WebSecurityConfigurer.class);
for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
webSecurityConfigurers.add(entry.getValue());
}
return webSecurityConfigurers;
}
}
SecurityConfigurer
安全配置接口類
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
/**
* Initialize the {@link SecurityBuilder}. Here only shared state should be created
* and modified, but not properties on the {@link SecurityBuilder} used for building
* the object. This ensures that the {@link #configure(SecurityBuilder)} method uses
* the correct shared objects when building.
*
* @param builder
* @throws Exception
*/
void init(B builder) throws Exception;
/**
* Configure the {@link SecurityBuilder} by setting the necessary properties on the
* {@link SecurityBuilder}.
*
* @param builder
* @throws Exception
*/
void configure(B builder) throws Exception;
}
WebSecurityConfigurer
繼承于SecurityConfigurer
public interface WebSecurityConfigurer<T extends SecurityBuilder<Filter>> extends
SecurityConfigurer<Filter, T> {
}
WebSecurityConfigurerAdapter
實現(xiàn)接口WebSecurityConfigurer娘侍,項目中繼承于此類進行配置
@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
WebSecurityConfigurer<WebSecurity> {
}
結(jié)論
@EnableWebSecurity 加載 WebSecurityConfiguration睦柴,其又去加載WebSecurityConfigurerAdapter(代碼里是加載WebSecurityConfigurer接口的實現(xiàn)類,但 WebSecurityConfiguration 中的成員變量是 SecurityConfigurer
認證服務(wù)安全配置類
@EnableAuthorizationServer
其加載AuthorizationServerSecurityConfiguration配置文件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AuthorizationServerEndpointsConfiguration.class, AuthorizationServerSecurityConfiguration.class})
public @interface EnableAuthorizationServer {
}
AuthorizationServerSecurityConfiguration
繼承于WebSecurityConfigurerAdapter翘盖,由@EnableAuthorizationServer注釋加載
此處就可以知道繼承于WebSecurityConfigurerAdapter的配置澎嚣,其最終由WebSecurityConfiguration加載
@Configuration
@Order(0)
@Import({ ClientDetailsServiceConfiguration.class, AuthorizationServerEndpointsConfiguration.class })
public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();
}
AuthorizationServerConfigurer
注入到AuthorizationServerSecurityConfiguration的成員變量configurers
public interface AuthorizationServerConfigurer {
/**
* Configure the security of the Authorization Server, which means in practical terms the /oauth/token endpoint. The
* /oauth/authorize endpoint also needs to be secure, but that is a normal user-facing endpoint and should be
* secured the same way as the rest of your UI, so is not covered here. The default settings cover the most common
* requirements, following recommendations from the OAuth2 spec, so you don't need to do anything here to get a
* basic server up and running.
*
* @param security a fluent configurer for security features
*/
void configure(AuthorizationServerSecurityConfigurer security) throws Exception;
/**
* Configure the {@link ClientDetailsService}, e.g. declaring individual clients and their properties. Note that
* password grant is not enabled (even if some clients are allowed it) unless an {@link AuthenticationManager} is
* supplied to the {@link #configure(AuthorizationServerEndpointsConfigurer)}. At least one client, or a fully
* formed custom {@link ClientDetailsService} must be declared or the server will not start.
*
* @param clients the client details configurer
*/
void configure(ClientDetailsServiceConfigurer clients) throws Exception;
/**
* Configure the non-security features of the Authorization Server endpoints, like token store, token
* customizations, user approvals and grant types. You shouldn't need to do anything by default, unless you need
* password grants, in which case you need to provide an {@link AuthenticationManager}.
*
* @param endpoints the endpoints configurer
*/
void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception;
}
AuthorizationServerConfigurerAdapter
繼承于AuthorizationServerConfigurer虑椎,用于簡化配置類實現(xiàn)
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
}
}
資源服務(wù)配置類
@EnableResourceServer
加載ResourceServerConfiguration配置類
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ResourceServerConfiguration.class)
public @interface EnableResourceServer {
}
ResourceServerConfiguration
繼承于WebSecurityConfigurerAdapter,由注釋@EnableResourceServer加載
@Configuration
public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter implements Ordered {
private int order = 3;
private List<ResourceServerConfigurer> configurers = Collections.emptyList();
/**
* @param configurers the configurers to set
*/
@Autowired(required = false)
public void setConfigurers(List<ResourceServerConfigurer> configurers) {
this.configurers = configurers;
}
}
ResourceServerConfigurer
資源服務(wù)的具體配置類纲爸,由ResourceServerConfiguration加載
public interface ResourceServerConfigurer {
/**
* Add resource-server specific properties (like a resource id). The defaults should work for many applications, but
* you might want to change at least the resource id.
*
* @param resources configurer for the resource server
* @throws Exception if there is a problem
*/
void configure(ResourceServerSecurityConfigurer resources) throws Exception;
/**
* Use this to configure the access rules for secure resources. By default all resources <i>not</i> in "/oauth/**"
* are protected (but no specific rules about scopes are given, for instance). You also get an
* {@link OAuth2WebSecurityExpressionHandler} by default.
*
* @param http the current http filter configuration
* @throws Exception if there is a problem
*/
void configure(HttpSecurity http) throws Exception;
}
ResourceServerConfigurerAdapter
實現(xiàn)ResourceServerConfigurer接口亥鸠,默認情況下繼承此類進行配置
public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
總結(jié):
- AuthorizationServerSecurityConfiguration與ResourceServerConfiguration其本質(zhì)繼承于WebSecurityConfigurerAdapter的配置類,其最終被WebSecurityConfiguration加載
- AuthorizationServerConfigurerAdapter與AuthorizationServerSecurityConfiguration
ResourceServerConfigurerAdapter與ResourceServerConfiguration的關(guān)系類似于WebSecurityConfigurerAdapter與WebSecurityConfiguration的關(guān)系识啦,但層次不一樣