Spring Security 及 OAuth2 中 **ConfigurerAdapter 的关系
Spring Security 及 OAuth2 中 WebSecurityConfigurerAdapter,
AuthorizationServerConfigurerAdapter,ResourceServerConfigurerAdapter 之间啥关系
安全服务配置类
@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
实现接口WebSecurityConfigurer,项目中继承于此类进行配置
@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
WebSecurityConfigurer<WebSecurity> {
}
结论
@EnableWebSecurity 加载 WebSecurityConfiguration,其又去加载WebSecurityConfigurerAdapter(代码里是加载WebSecurityConfigurer接口的实现类,但 WebSecurityConfiguration 中的成员变量是 SecurityConfigurer
认证服务安全配置类
@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,用于简化配置类实现
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 {
}
}
资源服务配置类
@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
资源服务的具体配置类,由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
实现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();
}
}
总结:
- AuthorizationServerSecurityConfiguration与ResourceServerConfiguration其本质继承于WebSecurityConfigurerAdapter的配置类,其最终被WebSecurityConfiguration加载
- AuthorizationServerConfigurerAdapter与AuthorizationServerSecurityConfiguration
ResourceServerConfigurerAdapter与ResourceServerConfiguration的关系类似于WebSecurityConfigurerAdapter与WebSecurityConfiguration的关系,但层次不一样
网友评论