Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed

Binary token取得の実装

本稿では、SAML Security token 取得の実装に続き、Binary token取得処理の実装について、紹介します。
動作環境については、上記ページに紹介してありますので、割愛します。

Mainコード

実装コードのメインとなる部分を以下に示します。

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;
}

★ポイント1
SOAPリクエストメッセージを作成する部分です。
%(samltoken)部分をSAML security token(SAML Assertion)に置換します。
%(siteurl)部分は、SharepointサイトURLに置換します。
appliction.propertiesの一部分を以下に示します。

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>

★ポイント2
ここからの処理は外部サイトにアクセスするので、Proxy環境にある場合はProxy設定と、Https通信設定が必要です。
詳細は次節を参照してください。

★ポイント3
レスポンスXMLから、XPathを利用してBinary tokenを抽出します。
wsse:BinarySecurityToken項目がnamespaceのものなので、XPathExpression生成時namespaceを渡す必要があります。

ProxyClientHttpRequestFactoryBuilderクラス

ProxyClientHttpRequestFactoryBuilderクラスのコードを以下に示します。

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
 
}

★ポイント1 HTTP Proxyを設定する部分です。ID/Password認証は必要ありません。

★ポイント2 Bouncy CastleプロバイダーをSecurity Providerとして登録する部分です。
詳細については、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」エラーが発生します。

コメント

コメントを入力. Wiki文法が有効です:
Z F I X O
 

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