Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed
差分
このページの2つのバージョン間の差分を表示します。
次のリビジョン | 前のリビジョン | ||
study:java:sharepointonline:implement1 [2021/07/15 09:14] – 作成 banana | study:java:sharepointonline:implement1 [2021/07/16 00:04] (現在) – [Main class code] banana | ||
---|---|---|---|
行 1: | 行 1: | ||
====== SAML Security token 取得の実装 ====== | ====== SAML Security token 取得の実装 ====== | ||
ここでは、[[study: | ここでは、[[study: | ||
+ | {{keywords> | ||
===== 動作環境について ===== | ===== 動作環境について ===== | ||
テスト環境についてですが、Java7(IBM J9 VM (build 2.6, JRE 1.7.0 Windows 7 amd64-64 Compressed References 20150701_255667 (JIT enabled, AOT enabled))で、テストを行いました。\\ | テスト環境についてですが、Java7(IBM J9 VM (build 2.6, JRE 1.7.0 Windows 7 amd64-64 Compressed References 20150701_255667 (JIT enabled, AOT enabled))で、テストを行いました。\\ | ||
行 37: | 行 37: | ||
httpclientとして、apacheのhttpclientを使用していますが、Okhttpを使っても構いません。\\ | httpclientとして、apacheのhttpclientを使用していますが、Okhttpを使っても構いません。\\ | ||
また、RestTemplateを使用するため、spring-webを導入しています。\\ | また、RestTemplateを使用するため、spring-webを導入しています。\\ | ||
- | 特に注目したいのは、boucycastleライブラリです。bouncycastleライブラリを導入する理由については、Binary token取得のjava実装編で紹介します。 | + | 特に注目して欲しい のは、boucycastleライブラリです。bouncycastleライブラリを導入する理由については、Binary token取得のjava実装編で紹介します。 |
+ | |||
+ | ===== Main class code ===== | ||
+ | 実装のメインになるコードを以下に示します。\\ | ||
+ | <code java> | ||
+ | private static final ResourceBundle RSC = ResourceBundle.getBundle(" | ||
+ | private static final String STS_AUTH_ENDPOINT = " | ||
+ | |||
+ | private Map< | ||
+ | |||
+ | static { | ||
+ | //register the prefix of NameSpace | ||
+ | namespacePrefixes.put(" | ||
+ | } | ||
+ | |||
+ | public String receiveSamlSecurityToken() { | ||
+ | String _token = ""; | ||
+ | try { | ||
+ | //request entity | ||
+ | RequestEntity< | ||
+ | | ||
+ | | ||
+ | | ||
+ | RestTemplate _restTemplate = new RestTemplate(); | ||
+ | _restTemplate.setRequestFactory(buildHttpComponentsClientHttpRequestFactory()); | ||
+ | |||
+ | ResponseEntity< | ||
+ | DOMResult _result = new DOMResult(); | ||
+ | |||
+ | Transformer _transformer = TransformerFactory.newInstance().newTransformer(); | ||
+ | _transformer.transform(new StringSource(_responseEntity.getBody()), | ||
+ | |||
+ | Document _definitionDocument = (Document) _result.getNode(); | ||
+ | final String XPATH_EXPRESSION = "// | ||
+ | Node _tokenNode = getXPathExpression(XPATH_EXPRESSION).evaluateAsNode(_definitionDocument); | ||
+ | _token = nodeToXmlString(_tokenNode); | ||
+ | |||
+ | if ("" | ||
+ | logger.error(" | ||
+ | } | ||
+ | |||
+ | } catch (Exception e) { | ||
+ | logger.error(" | ||
+ | } | ||
+ | return _token; | ||
+ | }// | ||
+ | |||
+ | //build SAML request envelope | ||
+ | private String buildSamlSecurityRequestEnvelope() { | ||
+ | //UserName token mapping | ||
+ | Map< | ||
+ | _mapRequest.put(" | ||
+ | _mapRequest.put(" | ||
+ | _mapRequest.put(" | ||
+ | //replace placeHolder | ||
+ | StringSubstitutor _substitutor = new StringSubstitutor(_mapRequest, | ||
+ | String _finalXMLRequest = _substitutor.replace(RSC.getString(" | ||
+ | |||
+ | return _finalXMLRequest; | ||
+ | }// | ||
+ | |||
+ | private HttpComponentsClientHttpRequestFactory buildHttpComponentsClientHttpRequestFactory() throws Exception { | ||
+ | return HttpComponentsClientHttpRequestFactoryBuilder.build(); | ||
+ | } | ||
+ | |||
+ | //create xPathExpression | ||
+ | private XPathExpression getXPathExpression(String expression) { | ||
+ | XPathExpression _xPathExpressioin = XPathExpressionFactory.createXPathExpression(expression, | ||
+ | return _xPathExpressioin; | ||
+ | } | ||
+ | |||
+ | //convert nodes to XML string | ||
+ | private String nodeToXmlString(Node node) throws Exception { | ||
+ | StringWriter _writer = new StringWriter(); | ||
+ | Transformer _transformer = TransformerFactory.newInstance().newTransformer(); | ||
+ | _transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, | ||
+ | _transformer.setOutputProperty(OutputKeys.INDENT, | ||
+ | _transformer.transform(new DOMSource(node), | ||
+ | |||
+ | return _writer.toString(); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ★Point1\\ | ||
+ | SAML requestメッセージを作成する部分になります。\\ | ||
+ | SOAP Envelopeメッセージ(xml)は、application.propertiesに格納されています。\\ | ||
+ | application.propertiesの中身を以下に示します。 | ||
+ | <code properties> | ||
+ | soap.auth.username=Sharepointユーザーアカウント | ||
+ | soap.auth.password=ユーザーパスワード | ||
+ | soap.saml.token.request=< | ||
+ | |||
+ | </ | ||
+ | |||
+ | ★Point2\\ | ||
+ | HttpComponentsClientHttpRequestFactoryを作成する部分です。\\ | ||
+ | ごく一般的設定になりますが、ポイントとしてUser-Agentの指定です。((User-Agentを指定する理由は、SharePointサイトからの調整を回避するためです。詳細は[[https:// | ||
+ | コードの一部分を以下に示します。 | ||
+ | <code java> | ||
+ | public class HttpComponentsClientHttpRequestFactoryBuilder { | ||
+ | public static HttpComponentsClientHttpRequestFactory build() { | ||
+ | final int TIMEOUT = 5; | ||
+ | //create connection manager | ||
+ | PoolingHttpClientConnectionManager _cm = new PoolingHttpClientConnectionManager(); | ||
+ | _cm.setMaxTotal(128); | ||
+ | _cm.setDefaultMaxPerRoute(24); | ||
+ | |||
+ | //request configuration | ||
+ | RequestConfig _requestConfig = RequestConfig.custom() | ||
+ | .setConnectTimeout(TIMEOUT * 1000) | ||
+ | .setConnectionRequestTimeout(TIMEOUT * 1000) | ||
+ | .setSocketTimeout(TIMEOUT * 1000) | ||
+ | .build(); | ||
+ | |||
+ | //create HttpClient | ||
+ | HttpClientBuilder _builder = HttpClientBuilder.create() | ||
+ | .setUserAgent(" | ||
+ | .setConnectionManager(_cm) | ||
+ | .setDefaultRequestConfig(_requestConfig); | ||
+ | |||
+ | HttpComponentsClientHttpRequestFactory _factory = new HttpComponentsClientHttpRequestFactory(_builder.build()); | ||
+ | |||
+ | return _factory; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | ★Point3\\ | ||
+ | SAML: | ||
+ | elementがnamespaceのものならXPathExpression生成時、namespaceを渡す必要があります。\\ | ||
+ | |||
+ | ★Point4\\ | ||
+ | 取り出したSAML: | ||
+ | そのため、ここでNodeをStringに変換しています。 | ||
+ | |||
+ | ~~DISCUSSION~~ | ||
+ |