spring-security-oauth2注解详解

Posted 一天不进步,就是退步!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring-security-oauth2注解详解相关的知识,希望对你有一定的参考价值。

spring-security-oauth2支持的注解有:

1.EnableOAuth2Client

适用于使用spring security,并且想从Oauth2认证服务器来获取授权的web应用环境代码中,它启用了一个Oauth2 客户端配置。为了更好的利用这个特性,需要在客户端应用中的DelegatingFilterProxy(代理一个名为oauth2ClientContextFilter)增加一个servlet filter。当filter配置到client app时,可以使用注解@AccessTokenRequest提供的另一个bean来创建一个Oauth2RequestTemplate。示例:

  @Configuration
  @EnableOAuth2Client
  public class RemoteResourceConfiguration {
  
   @Bean
   public OAuth2RestOperations restTemplate(OAuth2ClientContext oauth2ClientContext) {
          return new OAuth2RestTemplate(remote(), oauth2ClientContext);
      }
  
  }

Client App使用client credential授权,不需要AccessTokenRequest或者域内RestOperation(对app来说,状态是全局的),但在需要时仍然使用filter来触发OAuth2RestOperation来获取token。使用密码授权的app需要在RestOperation动作之前为OAuth2ProtectedResouceDetail设置认证属性,这就是说,resouce detail 本身也需要session(假设系统中有多个用户)。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(OAuth2ClientConfiguration.class)
public @interface EnableOAuth2Client {

}

 

实现OAuth2ClientConfiguration

@Configuration
public class OAuth2ClientConfiguration {

    @Bean
    public OAuth2ClientContextFilter oauth2ClientContextFilter() {
        OAuth2ClientContextFilter filter = new OAuth2ClientContextFilter();
        return filter;
    }

    @Bean
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    protected AccessTokenRequest accessTokenRequest(@Value("#{request.parameterMap}")
    Map<String, String[]> parameters, @Value("#{request.getAttribute(‘currentUri‘)}")
    String currentUri) {
        DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
        request.setCurrentUri(currentUri);
        return request;
    }
    
    @Configuration
    protected static class OAuth2ClientContextConfiguration {
        
        @Resource
        @Qualifier("accessTokenRequest")
        private AccessTokenRequest accessTokenRequest;
        
        @Bean
        @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
        public OAuth2ClientContext oauth2ClientContext() {
            return new DefaultOAuth2ClientContext(accessTokenRequest);
        }
        
    }

}

2. EnableAuthorizationServer

工具方法,用来在当前应用context里(必须是一个DispatcherServlet context)开启一个授权server(例如AuthorizationEndpoint)和一个TokenEndpoint。server的多个属性可以通过自定义AuthorizationServerConfigurer类型(如AuthorizationServerConfigurerAdapter的扩展)的Bean来定制。通过正常使用spring security的特色EnableWebSecurity,用户负责保证授权Endpoint(/oauth/authorize)的安全,但Token Endpoint(/oauth/token)将自动使用http basic的客户端凭证来保证安全。通过一个或者多个AuthorizationServerConfigurer提供一个ClientDetailService来注册client(必须)。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AuthorizationServerEndpointsConfiguration.class, AuthorizationServerSecurityConfiguration.class})
public @interface EnableAuthorizationServer {

}

2.1 AuthorizationServerEndpointsConfiguration

    private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

    @PostConstruct
    public void init() {
        for (AuthorizationServerConfigurer configurer : configurers) {
            try {
                configurer.configure(endpoints);
            } catch (Exception e) {
                throw new IllegalStateException("Cannot configure enpdoints", e);
            }
        }
        endpoints.setClientDetailsService(clientDetailsService);
    }

 

 

    @Component
    protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegistryPostProcessor {

        private BeanDefinitionRegistry registry;

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory,
                    JwtAccessTokenConverter.class, false, false);
            if (names.length > 0) {
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class);
                builder.addConstructorArgReference(names[0]);
                registry.registerBeanDefinition(TokenKeyEndpoint.class.getName(), builder.getBeanDefinition());
            }
        }

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            this.registry = registry;
        }

    }

2.2 AuthorizationServerSecurityConfiguration

@Configuration
@Order(0)
@Import({ ClientDetailsServiceConfiguration.class, AuthorizationServerEndpointsConfiguration.class })
public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private AuthorizationServerEndpointsConfiguration endpoints;

    @Autowired
    public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception {
        for (AuthorizationServerConfigurer configurer : configurers) {
            configurer.configure(clientDetails);
        }
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Over-riding to make sure this.disableLocalConfigureAuthenticationBldr = false
        // This will ensure that when this configurer builds the AuthenticationManager it will not attempt
        // to find another ‘Global‘ AuthenticationManager in the ApplicationContext (if available),
        // and set that as the parent of this ‘Local‘ AuthenticationManager.
        // This AuthenticationManager should only be wired up with an AuthenticationProvider
        // composed of the ClientDetailsService (wired in this configuration) for authenticating ‘clients‘ only.
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer();
        FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping();
        http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping);
        configure(configurer);
        http.apply(configurer);
        String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");
        String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");
        String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");
        if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
            UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
            endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
        }
        // @formatter:off
        http
            .authorizeRequests()
                .antMatchers(tokenEndpointPath).fullyAuthenticated()
                .antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess())
                .antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess())
        .and()
            .requestMatchers()
                .antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath)
        .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
        // @formatter:on
        http.setSharedObject(ClientDetailsService.class, clientDetailsService);
    }

    protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        for (AuthorizationServerConfigurer configurer : configurers) {
            configurer.configure(oauthServer);
        }
    }

}

 

以上是关于spring-security-oauth2注解详解的主要内容,如果未能解决你的问题,请参考以下文章

@Retention作用详析

Spring 中的 spring-security-oauth2 与 spring-security-oauth2-core

spring-security-oauth2 - 从资源服务器检查ClientDetails

MyBatis(详)

MyBatis(详)

spring-security-oauth2中的HttpSecurity配置问题