差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
study:java:sharepointonline:implement3 [2021/07/19 08:35] bananastudy:java:sharepointonline:implement3 [2025/02/03 09:17] (現在) banana
行 1: 行 1:
 ====== Binary token取得の実装 ====== ====== Binary token取得の実装 ======
 本稿では、[[study:java:sharepointonline:implement1|SAML Security token 取得の実装]]に続き、Binary token取得処理の実装について、紹介します。\\ 本稿では、[[study:java:sharepointonline:implement1|SAML Security token 取得の実装]]に続き、Binary token取得処理の実装について、紹介します。\\
 +動作環境については、上記ページに紹介してありますので、割愛します。
  
-===== Mainコード =====+{{keywords>Get Binary token Sharepoint online}} 
 + 
 +====== Mainコード ======
 実装コードのメインとなる部分を以下に示します。 実装コードのメインとなる部分を以下に示します。
 <code java> <code java>
 +private static final ResourceBundle RSC = ResourceBundle.getBundle("com.app.sample.ws.application");
 +private static final String CUSTOM_STS_ENDPOINT = "https://login.microsoftonline.com/extSTS.srf";
 +
 +private Map<String, String> namespacePrefixes = new HashMap<String, String>();
 +static {
 +  //register the prefix of NameSpace
 +  namespacePrefixes.put("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
 +}
 +
 +public String receiveBinarySecurityToken(String samlAssertion) {
 +  String _token = "";
 +  try {
 +    //request entity
 +    RequestEntity<String> _requestEntity = RequestEntity
 + .post(new URI(CUSTOM_STS_ENDPOINT))
 + .header("content-type", "application/soap+xml; charset=utf-8")
 + .body(buildBinaryTokenRequestEnvelope(samlAssertion));  ★ポイント1
 +
 +    RestTemplate _restTemplate = new RestTemplate();
 +    _restTemplate.setRequestFactory(buildProxyClientHttpRequestFactory());   ★ポイント2
 +
 +    ResponseEntity<String> _responseEntity = _restTemplate.exchange(_requestEntity, String.class);
 +    DOMResult _result = new DOMResult();
 +
 +    Transformer _transformer = TransformerFactory.newInstance().newTransformer();
 +    _transformer.transform(new StringSource(_responseEntity.getBody()), _result);
 +
 +    Document _definitionDocument = (Document) _result.getNode();
 +    final String XPATH_EXPRESSION = "//wsse:BinarySecurityToken";    ★ポイント3
 +    _token = getXPathExpression(XPATH_EXPRESSION).evaluateAsString(_definitionDocument);
 +
 +    if ("".equals(_token)) {
 + logger.error("Unable to authenticate: empty token");
 +    }
 +
 +  } catch (Exception e) {
 +    logger.error("failed to receive binary security token", e);
 +  }
 +
 +  return _token;
 +}//receiveBinarySecurityToken
 +
 +//build Binary token request envelope
 +private String buildBinaryTokenRequestEnvelope(String samlAssertion) {
 +  //SAML Assertion mapping
 +  Map<String, String> _mapRequest = new HashMap<String, String>();
 +  _mapRequest.put("samltoken", samlAssertion);
 +  _mapRequest.put("siteurl", RSC.getString("site.url"));
 +  //replace placeHolder
 +  StringSubstitutor _substitutor = new StringSubstitutor(_mapRequest, "%(", ")");
 +  String _finalXMLRequest = _substitutor.replace(RSC.getString("soap.binary.token.request"));
 +
 +  return _finalXMLRequest;
 +}//buildBinaryTokenRequestEnvelope
 +
 +//build HttpComponentsClientHttpRequestFactory for PROXY connection
 +private HttpComponentsClientHttpRequestFactory buildProxyClientHttpRequestFactory() throws Exception {
 +  return ProxyClientHttpRequestFactoryBuilder.build());
 +}
 +
 +//create XPathExpression
 +private XPathExpression getXPathExpression(String expression) {
 +  XPathExpression _xPathExpressioin = XPathExpressionFactory.createXPathExpression(expression, namespacePrefixes);
 +  return _xPathExpressioin;
 +}
  
 </code> </code>
 +
 +★ポイント1\\
 +SOAPリクエストメッセージを作成する部分です。\\
 +%(samltoken)部分をSAML security token(SAML Assertion)に置換します。\\
 +%(siteurl)部分は、SharepointサイトURLに置換します。\\
 +appliction.propertiesの一部分を以下に示します。
 +<code>
 +site.url=SharepointサイトURL
 +soap.binary.token.request=<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">%(samltoken)</o:Security></s:Header><s:Body><t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"><wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a:EndpointReference><a:Address>%(siteurl)</a:Address></a:EndpointReference></wsp:AppliesTo><t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType><t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType><t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType></t:RequestSecurityToken></s:Body></s:Envelope>
 +</code>
 +
 +★ポイント2\\
 +ここからの処理は外部サイトにアクセスするので、Proxy環境にある場合はProxy設定と、Https通信設定が必要です。\\
 +詳細は次節を参照してください。
 +
 +★ポイント3\\
 +レスポンスXMLから、XPathを利用してBinary tokenを抽出します。\\
 +wsse:BinarySecurityToken項目がnamespaceのものなので、XPathExpression生成時namespaceを渡す必要があります。
 +
 +====== ProxyClientHttpRequestFactoryBuilderクラス ======
 +ProxyClientHttpRequestFactoryBuilderクラスのコードを以下に示します。
 +<code java>
 +public class ProxyClientHttpRequestFactoryBuilder {
 +  private static final String PROXY_HOST = "proxy.sample.com";
 +  private static final int PROXY_PORT = 8080;
 +
 +  public static HttpComponentsClientHttpRequestFactory build() throws Exception {
 +    HttpHost _proxy = new HttpHost(PROXY_HOST, PROXY_PORT );
 +
 +    final int TIMEOUT = 5;
 +
 +    //request configuration
 +    RequestConfig _reqConfig = RequestConfig.custom()
 + .setConnectTimeout(TIMEOUT * 1000)
 +        .setSocketTimeout(TIMEOUT * 1000)
 + .setConnectionRequestTimeout(TIMEOUT * 1000)
 + .setProxy(_proxy)   ★ポイント1
 + .build();
 +
 +    BouncyCastleFipsProviderHelper.setUpProvider();   ★ポイント2
 +
 +    //setup SSLContext(BouncyCastle provider)
 +    SSLContext _sslContext = SSLContexts.custom()
 + .setProvider(new BouncyCastleJsseProvider(true))   ★ポイント3
 + .build();
 +
 +    SSLConnectionSocketFactory _sslSocketFactory = new SSLConnectionSocketFactory(_sslContext,
 + new String[]{"TLSv1.2"},
 + new String[]{"SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",    ★ポイント4
 + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"}, //key length=128制限があるため
 + new DefaultHostnameVerifier());
 +
 +    Registry<ConnectionSocketFactory> _socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
 + .register("http", PlainConnectionSocketFactory.getSocketFactory())
 + .register("https", _sslSocketFactory)
 + .build();
 +
 +    PoolingHttpClientConnectionManager _cm = new PoolingHttpClientConnectionManager(_socketFactoryRegistry);
 + _cm.setMaxTotal(200);
 + _cm.setDefaultMaxPerRoute(100);
 +
 +    //create HttpClient
 +    HttpClient _client = HttpClientBuilder.create()
 + .setUserAgent("NONISV|Nskcom|Sharepoint-demo/1.0") //NONISV|CompanyName|AppName/Version
 + .setConnectionManager(_cm)
 + .disableRedirectHandling()
 + .setDefaultRequestConfig(_reqConfig)
 + .build();
 +
 +    HttpComponentsClientHttpRequestFactory _factory = new HttpComponentsClientHttpRequestFactory(_client);
 +
 +    return _factory;
 +  }//build
 +
 +}
 +</code>
 +
 +★ポイント1
 +HTTP Proxyを設定する部分です。ID/Password認証は必要ありません。
 +
 +★ポイント2
 +Bouncy CastleプロバイダーをSecurity Providerとして登録する部分です。\\
 +詳細については、[[study:java:sharepointonline:implement2|3rd Party Security Providerの導入について]]を参照してください。
 +
 +★ポイント3
 +FIPSモードとしてBouncy castleプロバイダーを設定します。
 +
 +★ポイント4
 +Cipher Suiteを指定します。 Java 7環境では、key size制限(128)があるため、Sharepointサイト要求のCipher Suiteから128lengthのみを選択します。\\
 +この指定がないと、「java.security.InvalidKeyException: Illegal key size」エラーが発生します。
 +
 +~~DISCUSSION~~

QR Code
QR Code study:java:sharepointonline:implement3 (generated for current page)