5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SAP連携、認証方法毎のAPI呼び出し方法

Last updated at Posted at 2024-11-25

はじめに

SAP BTPでSideBySideを行っている中、
SAPソリューションと連携を行う際、DestinationServiceに認証情報を定義し、DestinationServiceを用いてSAPソリューションのAPIをコールすることがあるかと思います。
今回はDestinationServiceに定義した認証情報毎にAPIの呼び出し方法をJavaでどのように実装するか投稿したいと思います。

Basic認証の場合

・SAP Cloud SDKを用いて、DestinationServiceに定義された情報を取得する
・取得した情報をもとにHttpClientを生成し、HttpClientを使ってHttpReqestを実行する

JAVAのコード例

// DestinationServiceに定義された情報を取得
HttpDestination destination = DestinationAccessor.getDestination(DESTINATION_NAME).asHttp();

// DestinationServiceに定義されたURL
String baseUrl = destination.getUri().toString();

// Destinationの情報からHttpClientを取得
HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);

// 上記のhttpClientを用いてGet処理を実行
HttpGet request = new HttpGet(baseUrl + "/sap/opu/odata/sap/XXXX_SRV/XXXXEntity");
CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(request);

SAP Cloud SDKを使い、DestinationAccessor#getDestinationで
destinationの情報を取得すると、その中に認証情報もはいいてるので、
そのままHttpClient化→それを使用してHttpResponseを投げるといった単純なコードで
処理が可能です。
また、DestinationServiceにID/PWを定義するので、
ソースコードにID/PWを定義する必要もなく、ID/PW管理等余計な考慮も不要になります。

クライアント証明書の場合

・SAP Cloud SDKを用いて、DestinationServiceに定義された情報を取得する
・DestinationServiceに設定されている証明書を生成する
・HttpClientを生成し、作成時に証明を設定する

JAVAのコード例

// DestinationServiceに定義された情報を取得
HttpDestination destination = DestinationAccessor.getDestination(DESTINATION_NAME).asHttp();

// DestinationServiceに定義されたURL
String baseUrl = destination.getUri().toString();

// Destinationの情報からHttpClientを取得
HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
String keyStorePassword = destination.getKeyStorePassword().get().toString();

// 証明書情報(content)の取得
List<DestinationCertificate> certificateValue = (List<DestinationCertificate>) destination.get("certificates").get();
String contentValue = certificateValue.get(0).getContent().toString();
byte[] contentBytes = Base64.getDecoder().decode(contentValue);

// keyStoreのload
try (InputStream certInputStream = new ByteArrayInputStream(contentBytes)) {
    keyStore.load(certInputStream, keyStorePassword.toCharArray());       }

 // SSLContextの構築
SSLContext sslContext = SSLContextBuilder.create()
                    .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
                    .build();

// HttpClientの生成
HttpClient client = HttpClients.custom()
            .setSSLContext(tsslContext)
            .build();

// 上記のhttpClientを用いてGet処理を実行
HttpGet request = new HttpGet(baseUrl + "/sap/opu/odata/sap/XXXX_SRV/XXXXEntity");
CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(request);

Basic認証の時と違い、Destinationから生成するHttpClientでは、証明書を送付していないような動きとなってしまい、認証エラーとなったので、
別でSSLContextの生成と、HttpClientの生成を行いました。

DestinationServiceから証明書を取得する際は、Base64形式であることや
SSLContext生成時にIOが発生する。
HttpClientを独自に行わないといけないので、TimeOut設定等が必要になる。
(上記のサンプルコードはTimeOut設定は記載していない)
等の考慮が必要ですが、こちらも証明書やパスフレーズをソース上に管理する必要が無く、証明書の更新等はService上で行うことができプログラム側の影響が少なくすみます。

SAML Bearer Assertion (OAuth2.0) Authenticationの場合

・JavaへReqest時に送付されるTokenを用いてDestinationServiceに定義された情報を取得する
・取得した情報をもとにHttpClientを生成し、HttpClientを使ってHttpReqestを実行する

// TokenよりをJWTにでコードし、認証Tokenを取得
DecodedJWT decodedJWT = JWT.decode(token.getAppToken());
AuthToken authToken = new AuthToken(decodedJWT);

// 認証Tokenを用いてDestinationServiceより定義を取得
HttpDestination destination = AuthTokenAccessor.executeWithAuthToken(authToken,
                                () -> DestinationAccessor.getDestination(DESTINATION_NAME)).asHttp();

// DestinationServiceに定義されたURL
String baseUrl = destination.getUri().toString();

@SuppressWarnings("unchecked")
List<DestinationAuthToken> authTokensValue = (List<DestinationAuthToken>) destination.get("authTokens").get();
String accessToken = authTokensValue.get(0).getValue();


// HttpClientの生成
HttpClient httpClient = HttpClients.createDefault();

HttpPost postRequest = new HttpPost(baseUrl + "/sap/opu/odata/sap/XXXX_SRV/XXXXEntity"););
postRequest.setEntity(new StringEntity(payLoads.toString(), "UTF-8"));
postRequest.addHeader("Authorization", "Bearer " + accessToken);
httpClient.execute(postRequest);

SAML Bearer Assertion (OAuth2.0) Authenticationを使う場合は、
Cloud Identity Services(IAS)でユーザ管理し、SAP BTPとS/4HanaやSuccessFactorsがIAS管理のもとSSO認証ができる状態になっているのが大前提ではあり、DestinationServiceの定義も少し複雑ではありますが、SAPソリューション側の権限に則したデータ登録、取得が可能になります。

まとめ

Basic認証やクライアント証明書はSAPソリューションに限らず登場すると思いますが、
SAML Bearer Assertionを用いた認証はS/4HanaやSuccessFactorsとSSO認証がIASを用いて容易にできるBTPならではの認証方式かと思います。
SAPUI5(Fiori)から直接コールする場合はDestinationServiceの定義だけでよかったのですが、SAPUI5(Fiori)→JAVA→SAPソリューションの流れでAPIをコールする時に苦労したので、今回記事にしました。
別途JAVAでToken(ユーザ情報)の取得する処理は以下に投稿しているので、こちらも参考にしていただければと思います。
https://qiita.com/kojirousan/items/029f10f1809ace2cecfd

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?