Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed
文書の過去の版を表示しています。
Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed
SAML Security token 取得の実装
ここでは、POC of consuming Sharepoint onlineのPOC段階2について、Javaの実装例を紹介します。
動作環境について
テスト環境についてですが、Java7(IBM J9 VM (build 2.6, JRE 1.7.0 Windows 7 amd64-64 Compressed References 20150701_255667 (JIT enabled, AOT enabled))で、テストを行いました。
ビルドには、Mavenを使用しました。
必要なlibrary dependencyを以下に示します。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.25.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.3</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20210307</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bctls-fips</artifactId> <version>1.0.12.1</version> <scope>provided</scope> </dependency>
httpclientとして、apacheのhttpclientを使用していますが、Okhttpを使っても構いません。
また、RestTemplateを使用するため、spring-webを導入しています。
特に注目して欲しい のは、boucycastleライブラリです。bouncycastleライブラリを導入する理由については、Binary token取得のjava実装編で紹介します。
Main class code
実装のメインになるコードを以下に示します。
private static final ResourceBundle RSC = ResourceBundle.getBundle("com.app.sample.ws.application"); private static final String STS_AUTH_ENDPOINT = "https://xxxxx.contoso.com/adfs/services/trust/2005/usernamemixed"; private Map<String, String> namespacePrefixes = new HashMap<String, String>(); static { //register the prefix of NameSpace namespacePrefixes.put("t", "http://schemas.xmlsoap.org/ws/2005/02/trust"); } public String receiveSamlSecurityToken() { String _token = ""; try { //request entity RequestEntity<String> _requestEntity = RequestEntity .post(new URI(STS_AUTH_ENDPOINT)) .header("content-type", "application/soap+xml; charset=utf-8") .body(buildSamlSecurityRequestEnvelope()); ★Point1 RestTemplate _restTemplate = new RestTemplate(); _restTemplate.setRequestFactory(buildHttpComponentsClientHttpRequestFactory()); 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 = "//t:RequestedSecurityToken/*"; Node _tokenNode = getXPathExpression(XPATH_EXPRESSION).evaluateAsNode(_definitionDocument); _token = nodeToXmlString(_tokenNode); if ("".equals(_token)) { logger.error("Unable to authenticate: empty token"); } } catch (Exception e) { logger.error("failed to receive SAML security token", e); } return _token; }//receiveSamlSecurityToken //build SAML request envelope private String buildSamlSecurityRequestEnvelope() { //UserName token mapping Map<String, String> _mapRequest = new HashMap<String, String>(); _mapRequest.put("sts_auth_url", STS_AUTH_ENDPOINT); _mapRequest.put("loginuser", RSC.getString("soap.auth.username")); _mapRequest.put("loginpass", RSC.getString("soap.auth.password")); //replace placeHolder StringSubstitutor _substitutor = new StringSubstitutor(_mapRequest, "%(", ")"); String _finalXMLRequest = _substitutor.replace(RSC.getString("soap.saml.token.request")); return _finalXMLRequest; }//buildSamlSecurityRequestEnvelope private HttpComponentsClientHttpRequestFactory buildHttpComponentsClientHttpRequestFactory() throws Exception { return HttpComponentsClientHttpRequestFactoryBuilder.build(); } //create xPathExpression private XPathExpression getXPathExpression(String expression) { XPathExpression _xPathExpressioin = XPathExpressionFactory.createXPathExpression(expression, namespacePrefixes); 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, "yes"); _transformer.setOutputProperty(OutputKeys.INDENT, "no"); _transformer.transform(new DOMSource(node), new StreamResult(_writer)); return _writer.toString(); }
★Point1
SAML requestメッセージを作成する部分になります。
SOAP Envelopeメッセージ(xml)は、application.propertiesに格納されています。
application.propertiesの中身を以下に示します。
soap.auth.username=N906076@nsk.com soap.auth.password=N906076 soap.saml.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><a:To s:mustUnderstand="1">%(sts_auth_url)</a:To><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><o:UsernameToken><o:Username>%(loginuser)</o:Username><o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">%(loginpass)</o:Password></o:UsernameToken></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>urn:federation:MicrosoftOnline</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>
コメント