差分

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

この比較画面へのリンク

次のリビジョン
前のリビジョン
study:java:sharepointonline:implement3 [2021/07/19 08:29] – 作成 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取得処理の実装について、紹介します。\\ 
 +動作環境については、上記ページに紹介してありますので、割愛します。 
 + 
 +{{keywords>Get Binary token Sharepoint online}} 
 + 
 +====== Mainコード ====== 
 +実装コードのメインとなる部分を以下に示します。 
 +<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> 
 + 
 +★ポイント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)