Spring Security 及 OAuth2 中 **ConfigurerAdapter 的关系

Spring Security 及 OAuth2 中 **ConfigurerAdapter 的关系

Spring SecurityOAuth2WebSecurityConfigurerAdapter,
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();
    }

}

总结:

  • AuthorizationServerSecurityConfigurationResourceServerConfiguration其本质继承于WebSecurityConfigurerAdapter的配置类,其最终被WebSecurityConfiguration加载
  • AuthorizationServerConfigurerAdapterAuthorizationServerSecurityConfiguration
    ResourceServerConfigurerAdapterResourceServerConfiguration的关系类似于WebSecurityConfigurerAdapterWebSecurityConfiguration的关系,但层次不一样
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容