【问题标题】:Spring Boot + Oauth2 client credentialsSpring Boot + Oauth2 客户端凭据
【发布时间】:2016-09-28 18:43:00
【问题描述】:

我正在尝试使用带有客户端凭据流的 Oath2 在 Spring Boot 上保护我的微服务。

顺便说一句,这些微服务只会通过中间件层相互通信,我的意思是不需要用户凭据来允许授权(用户登录过程为 Facebook)。

我在 Internet 上寻找了展示如何创建授权和资源服务器来管理此通信的示例。但是,我刚刚找到了解释如何使用用户凭据(三条腿)进行操作的示例。

有没有人有任何示例如何在 Spring Boot 和 Oauth2 中做到这一点?如果可以提供有关所使用范围的更多详细信息,将不胜感激。

【问题讨论】:

    标签: java spring spring-security spring-boot oauth-2.0


    【解决方案1】:

    我们使用 Oauth2 客户端凭据方案保护 REST 服务。资源和授权服务在同一个应用中运行,但可以拆分到不同的应用中。

    @Configuration
    public class SecurityConfig {
    
    @Configuration
    @EnableResourceServer
    protected static class ResourceServer extends ResourceServerConfigurerAdapter {
    
        // Identifies this resource server. Usefull if the AuthorisationServer authorises multiple Resource servers
        private static final String RESOURCE_ID = "*****";
    
        @Resource(name = "OAuth")
        @Autowired
        DataSource dataSource;
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http    
                    .authorizeRequests().anyRequest().authenticated();
            // @formatter:on
        }
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId(RESOURCE_ID);
            resources.tokenStore(tokenStore());
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
    }
    
    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    
        @Resource(name = "OAuth")
        @Autowired
        DataSource dataSource;
    
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenStore(tokenStore());
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
        }
    }
    }
    

    Oauth2 表的数据源配置:

    @Bean(name = "OAuth")
    @ConfigurationProperties(prefix="datasource.oauth")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    

    与认证&资源服务器通信如下

    curl -H "Accept: application/json" user:password@localhost:8080/oauth/token -d grant_type=client_credentials
    curl -H "Authorization: Bearer token" localhost:8080/...
    

    Oauth2 数据库中存在以下记录:

    client_id  resource_ids  client_secret  scope  authorized_grant_types   web_server_redirect_uri  authorities  access_token_validity refresh_token_validity  additional_information  autoapprove
    user  ****  password  NULL  client_credentials  NULL  X  NULL  NULL  NULL  NULL
    

    客户端应用程序中的 Resttemplate 配置

    @Configuration
    @EnableOAuth2Client
    public class OAuthConfig {
    
    @Value("${OAuth2ClientId}")
    private String oAuth2ClientId;
    
    @Value("${OAuth2ClientSecret}")
    private String oAuth2ClientSecret;
    
    @Value("${Oauth2AccesTokenUri}")
    private String accessTokenUri;
    
    @Bean
    public RestTemplate oAuthRestTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setId("1");
        resourceDetails.setClientId(oAuth2ClientId);
        resourceDetails.setClientSecret(oAuth2ClientSecret);
        resourceDetails.setAccessTokenUri(accessTokenUri);
    
        /*
    
        When using @EnableOAuth2Client spring creates a OAuth2ClientContext for us:
    
        "The OAuth2ClientContext is placed (for you) in session scope to keep the state for different users separate.
        Without that you would have to manage the equivalent data structure yourself on the server,
        mapping incoming requests to users, and associating each user with a separate instance of the OAuth2ClientContext."
        (http://projects.spring.io/spring-security-oauth/docs/oauth2.html#client-configuration)
    
        Internally the SessionScope works with a threadlocal to store variables, hence a new thread cannot access those.
        Therefore we can not use @Async
    
        Solution: create a new OAuth2ClientContext that has no scope.
        *Note: this is only safe when using client_credentials as OAuth grant type!
    
         */
    
    //        OAuth2RestTemplate restTemplate = new      OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, new DefaultOAuth2ClientContext());
    
        return restTemplate;
    }
    }
    

    您可以注入 restTemplate 以与 Oauth2 安全服务进行(异步)对话。 我们目前不使用作用域。

    【讨论】:

    • 除了使用@value 提取数据并设置oauthRestTemplate 之外,还有其他方法吗?
    • @CarlosAlberto 嗨,您有完整的项目吗?我也需要同样的。
    • 在资源服务器配置中,我们如何以编程方式设置userInfoUrl?有没有办法在ClientCredentialsResourceDetails 或其他对象中设置它?
    • 你把public DataSource secondaryDataSource()放在哪里?我试了两个不同的地方,都报错了。
    • oauth2数据库/表是自动创建的吗?您能否也发布“datasource.oauth”的配置属性?
    猜你喜欢
    • 2020-01-18
    • 2023-04-09
    • 2018-09-15
    • 2021-12-22
    • 2018-08-22
    • 2019-05-03
    • 2017-08-22
    • 2019-07-06
    • 2018-11-09
    相关资源
    最近更新 更多