首页 > 代码库 > spring-security-oauth2注解详解

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

@Configurationpublic 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注解详解