2016-10-05 4 views
0

私は次の問題を抱えています。オンラインAPIにアクセスするには、認証を取得する必要があります。今、私は自分自身のコードですべての操作を行います。OAuth2ベアラトークン要求にコールをラップするためにSpring Boot/Spring Securityを使用するにはどうすればよいですか?

  1. コール
  2. が結果を取得
  3. コールトークンベアラ
  4. と実際のサービストークンベアラーを取得したトークンベアラのトークンURLを
  5. ここで

はコードです:

@RestController 
public class RandomController { 

    private final Random random; 

    public RandomController(Random random) { 
     this.random = random; 
    } 

    @RequestMapping(value = "/get", method = GET) 
    public int random(@RequestParam(value = "limit", defaultValue = "100") int limit) { 
     String bearerToken = getBearerToken(); 
     int[] bounds = getBounds(bearerToken); 
     return computeRandom(bounds[0], bounds[1]); 
    } 

    private String getBearerToken() { 
     RestTemplate tokenTemplate = new RestTemplate(); 
     MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); 
     body.add("client_id", "my id"); 
     body.add("client_secret", "my secret"); 
     body.add("grant_type", "client_credentials"); 
     HttpHeaders headers = new HttpHeaders(); 
     headers.add("Accept", "application/json"); 
     HttpEntity<?> entity = new HttpEntity<>(body, headers); 
     ResponseEntity<String> res = tokenTemplate.exchange(
       "https://bearer.token/get", POST, entity, String.class); 
     Map<String, Object> map = new BasicJsonParser().parseMap(res.getBody()); 
     return (String) map.get("access_token"); 
    } 

    private int[] getBounds(String bearerToken) { 
     RestTemplate configurationTemplate = new RestTemplate(); 
     HttpHeaders headers = new HttpHeaders(); 
     headers.add("Authorization", "Bearer " + bearerToken); 
     HttpEntity<?> entity = new HttpEntity<>(headers); 
     ResponseEntity<String> res = configurationTemplate.exchange(
       "https://configurations.com/bounds", HttpMethod.GET, entity, String.class); 
     Map<String, Object> map = new BasicJsonParser().parseMap(res.getBody()); 
     Map<String, Long> value = (Map<String, Long>) map.get("value"); 
     int lowerBound = value.get("lower").intValue(); 
     int upperBound = value.get("upper").intValue(); 
     return new int[]{lowerBound, upperBound}; 
    } 

    private int computeRandom(int lowerBound, int upperBound) { 
     int difference = upperBound - lowerBound; 
     int raw = random.nextInt(difference); 
     return raw + lowerBound; 
    } 
} 

それは動作しますが、すべての呼び出しでトークンURLへの呼び出しを無駄にしています。これは、私はそれが動作したい方法です:401

  1. を得ることが
  2. トークンベアラのトークンURLが
  3. ベアラがトークンを取得呼び出す場合

    1. は、実際のサービス
    2. を呼び出し
    3. ベアラトークンを使用したサービスを呼び出す

私は自分のコードでそれを行うことができましたが、私はすでにSpring Bootを使用しています。私はそれを達成する方法が不思議です。既存のフィルタ、インターセプタなどはありますか?

あなたの洞察をお寄せいただきありがとうございます。

答えて

1

使用するクラスはOAuth2RestTemplateです。ただし、そのコンストラクタはOAuth2ProtectedResourceDetailsの実装を必要とします。

client_credentialを使用する実装は、ClientCredentialsResourceDetailsです。私はちょうど私のコンフィギュレーションクラスに@EnableOAuth2Clientを追加し、application.ymlに必要な情報を設定することは十分だろうことを期待していた:

security: 
    oauth2: 
     client: 
      grant-type: client_credentials 
      client-id: my id 
      client-secret: my secret 
      access-token-uri: https://bearer.token/get 

残念ながら、それは動作しません。その理由は、クラスOAuth2RestOperationsConfigurationで見つけることができます: - 誤っ、唯一の非Webアプリケーションがクライアントの資格情報の認証を使用することができることを

@Configuration 
@ConditionalOnClass(EnableOAuth2Client.class) 
@Conditional(OAuth2ClientIdCondition.class) 
public class OAuth2RestOperationsConfiguration { 

    @Configuration 
    @ConditionalOnNotWebApplication 
    protected static class SingletonScopedConfiguration { 

     @Bean 
     @ConfigurationProperties("security.oauth2.client") 
     @Primary 
     public ClientCredentialsResourceDetails oauth2RemoteResource() { 
      ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); 
      return details; 
     } 
     ... 
    } 
    ... 
} 

Springフレームワークを前提としているようです。私の場合は、これがプロバイダが提供する唯一の方法です。

関連するスニペットは、コピー&ペーストすることができます:-)

私の最終的なコードは次のようになりかかわら:私はOAuth2RestTemplateRestTemplateを置き換えるために、コントローラは、はるかに少ない定型を取得することを

@SpringBootApplication 
public class RandomApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(RandomApplication.class, args); 
    } 

    @Bean 
    @ConfigurationProperties("security.oauth2.client") 
    ClientCredentialsResourceDetails clientCredentialsResourceDetails() { 
     return new ClientCredentialsResourceDetails(); 
    } 

    @Bean 
    OAuth2RestTemplate oAuth2RestTemplate() { 
     return new OAuth2RestTemplate(clientCredentialsResourceDetails()); 
    } 

    @Bean 
    Random random() { 
     return new SecureRandom(); 
    } 
} 

@RestController 
public class RandomController { 

    private final OAuth2RestTemplate oAuth2RestTemplate; 
    private final Random random; 

    public RandomController(OAuth2RestTemplate oAuth2RestTemplate, Random random) { 
     this.oAuth2RestTemplate = oAuth2RestTemplate; 
     this.random = random; 
    } 

    @RequestMapping(value = "/get", method = GET) 
    public int random() { 
     int[] bounds = getBounds(); 
     return computeRandom(bounds[0], bounds[1]); 
    } 

    private int[] getBounds() { 
     ResponseEntity<String> res = oAuth2RestTemplate.getForEntity(
       "https://configurations.com/bounds", String.class); 
     Map<String, Object> map = new BasicJsonParser().parseMap(res.getBody()); 
     Map<String, Long> value = (Map<String, Long>) map.get("value"); 
     int lowerBound = value.get("lower").intValue(); 
     int upperBound = value.get("upper").intValue(); 
     return new int[]{lowerBound, upperBound}; 
    } 

    private int computeRandom(int lowerBound, int upperBound) { 
     int difference = upperBound - lowerBound; 
     int raw = random.nextInt(difference); 
     return raw + lowerBound; 
    } 
} 

注意してください。

1

Spring SecurityのOAuth2RestTemplateを試してみてください。トークンを取得し、可能であればキャッシングする必要があります。これは設定ファイルで設定し、APIを呼び出すたびに注入する必要があります。

+0

私はあなたの答えをアップアップします:a)それは唯一のものです - ありがとう:) b)それは正しい方向に転がりました。 まだ、私はより詳細な何かを期待していました。私は最終的に私が最小限のコードで欲しいものを達成する方法を見つけました。ドキュメンテーションのために、私は自分の質問に答えていきます。 – Nicolas

関連する問題