2016-11-15 25 views
0

私はAzureを初めて使用しています。Javaを使用してAzureのOffice 365(共有ポイントREST API)にアクセス

私はSharepointでJavaを統合しようとしています。 Sharepoint-Office 365は、Azure ADFSで利用できます。私はJavaプログラムを書いて認証し、Sharepointが提供するRESTfulなAPIを使ってファイルにアクセスする必要があります。 AzureはWS-Federation認証プロセスを使用しています。私はWS-F認証を使用してファイルにアクセスするのに役立つコードを探しています。私は有用な資料を見つけることができません。

基本認証が機能していないため、私はWS-F認証を受けていませんでした。だから、どこから始めるべきかの手がかりはない。私はOffice-365-sdkも使っていましたが、私のアプリケーションに関係のないクライアントIDやその他の属性を使っているので、それを行うことはできませんでした。例えば、sharepointはすでに利用可能であるため、クライアントIDは必要ありません。

私はthis linkも得ましたが、いくつかの方法が欠落しており、達成に使用されたライブラリについて説明していません。これを実装する際に私を案内してください。ここで

+0

あなたのブログへのリンクをどのように見つけましたか教えてください。 – Maksim

+0

@マクシム、適切な文言でグーグル、かもしれない.... – Anand

答えて

0

はあなたが言及articleからのコードです:次のように、このサービスから

package com.waveaccess.someproject.commons.service; 

import com.waveaccess.someproject.commons.config.Const; 
import com.waveaccess.someproject.commons.config.properties.SharePointProperties; 
import com.waveaccess.someproject.commons.service.exceptions.SharePointAuthenticationException; 
import com.waveaccess.someproject.commons.service.exceptions.SharePointSignInException; 
import com.google.common.base.Joiner; 
import org.apache.commons.collections.CollectionUtils; 
import org.apache.commons.lang3.StringUtils; 
import org.json.JSONException; 
import org.json.JSONObject; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.cache.annotation.Cacheable; 
import org.springframework.http.HttpHeaders; 
import org.springframework.http.HttpMethod; 
import org.springframework.http.RequestEntity; 
import org.springframework.http.ResponseEntity; 
import org.springframework.stereotype.Service; 
import org.springframework.util.LinkedMultiValueMap; 
import org.springframework.util.MultiValueMap; 
import org.springframework.web.client.RestTemplate; 
import org.springframework.xml.transform.StringSource; 
import org.springframework.xml.xpath.XPathExpression; 
import org.w3c.dom.Document; 

import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.dom.DOMResult; 
import java.io.IOException; 
import java.net.URI; 
import java.net.URISyntaxException; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.List; 

/** 
* @author Maksim Kanev 
*/ 
@Service 
public class SharePointServiceCached { 

    private static final Logger log = LoggerFactory.getLogger(SharePointServiceCached.class); 

    @Autowired 
    private RestTemplate restTemplate; 

    @Autowired 
    private SharePointProperties sharePointProperties; 

    @Autowired 
    private XPathExpression xPathExpression; 

    @Cacheable(Const.CACHE_NAME_TOKEN) 
    public String receiveSecurityToken(Long executionDateTime) throws TransformerException, URISyntaxException { 
     RequestEntity<String> requestEntity = new RequestEntity<>(buildSecurityTokenRequestEnvelope(), HttpMethod.POST, new URI(sharePointProperties.getEndpoint() + "/extSTS.srf")); 
     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(); 

     String securityToken = xPathExpression.evaluateAsString(definitionDocument); 
     if (StringUtils.isBlank(securityToken)) { 
      throw new SharePointAuthenticationException("Unable to authenticate: empty token"); 
     } 
     log.debug("Microsoft Online respond with Token: {}", securityToken); 
     return securityToken; 
    } 

    private String buildSecurityTokenRequestEnvelope() { 
     String envelopeTemplate = "<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\">https://login.microsoftonline.com/extSTS.srf</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>%s</o:Username> <o:Password>%s</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>" + sharePointProperties.getEndpoint() + "</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>"; 
     return String.format(envelopeTemplate, sharePointProperties.getUsername(), sharePointProperties.getPassword()); 
    } 

    @Cacheable(Const.CACHE_NAME_COOKIE) 
    public List<String> getSignInCookies(String securityToken) throws TransformerException, URISyntaxException { 
     RequestEntity<String> requestEntity = new RequestEntity<>(securityToken, HttpMethod.POST, new URI(sharePointProperties.getEndpoint() + "/_forms/default.aspx?wa=wsignin1.0")); 
     ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class); 
     HttpHeaders headers = responseEntity.getHeaders(); 
     List<String> cookies = headers.get("Set-Cookie"); 
     if (CollectionUtils.isEmpty(cookies)) { 
      throw new SharePointSignInException("Unable to sign in: no cookies returned in response"); 
     } 
     log.debug("SharePoint respond with cookies: {}", Joiner.on(", ").join(cookies)); 
     return cookies; 
    } 

    public String getFormDigestValue(List<String> cookies) throws IOException, URISyntaxException, TransformerException, JSONException { 
     MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); 
     headers.add("Cookie", Joiner.on(';').join(cookies)); 
     headers.add("Accept", "application/json;odata=verbose"); 
     headers.add("X-ClientService-ClientTag", "SDK-JAVA"); 
     RequestEntity<String> requestEntity = new RequestEntity<>(headers, HttpMethod.POST, new URI(sharePointProperties.getEndpoint() + "/_api/contextinfo")); 
     ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class); 
     JSONObject json = new JSONObject(responseEntity.getBody()); 
     return json.getJSONObject("d") 
       .getJSONObject("GetContextWebInformation") 
       .getString("FormDigestValue"); 
    } 

    public Long parseExecutionDateTime(Date dateTime) { 
     if (dateTime == null) 
      return null; 
     final Calendar cal = Calendar.getInstance(); 
     cal.setTime(dateTime); 
     cal.set(Calendar.HOUR_OF_DAY, 0); 
     cal.set(Calendar.MINUTE, 0); 
     cal.set(Calendar.SECOND, 0); 
     cal.set(Calendar.MILLISECOND, 0); 
     return cal.getTime().getTime(); 
    } 

} 

メソッドが呼び出されなければならない:

package com.waveaccess.someproject.commons.service; 

import com.google.common.base.Joiner; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpMethod; 
import org.springframework.http.RequestEntity; 
import org.springframework.http.ResponseEntity; 
import org.springframework.stereotype.Service; 
import org.springframework.util.LinkedMultiValueMap; 
import org.springframework.util.MultiValueMap; 
import org.springframework.web.client.RestTemplate; 

import java.net.URI; 
import java.util.Date; 
import java.util.List; 

/** 
* @author Maksim Kanev 
*/ 
@Service 
public class SharePointService { 

    private static final Logger log = LoggerFactory.getLogger(SharePointService.class); 

    @Autowired 
    private SharePointServiceCached serviceCached; 

    @Autowired 
    private RestTemplate restTemplate; 

    public String performHttpRequest(HttpMethod method, String path) throws Exception { 
     Long executionDateTime = serviceCached.parseExecutionDateTime(new Date()); 
     String securityToken = serviceCached.receiveSecurityToken(executionDateTime); 
     List<String> cookies = serviceCached.getSignInCookies(securityToken); 
     MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); 
     headers.add("Cookie", Joiner.on(';').join(cookies)); 
     RequestEntity<String> requestEntity = new RequestEntity<>(headers, method, new URI(path)); 
     ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class); 
     String responseBody = responseEntity.getBody(); 
     log.debug(responseBody); 
     return responseBody; 
    } 

    public String performHttpRequest(String path, String json, boolean isUpdate, boolean isWithDigest) throws Exception { 
     Long executionDateTime = serviceCached.parseExecutionDateTime(new Date()); 
     String securityToken = serviceCached.receiveSecurityToken(executionDateTime); 
     List<String> cookies = serviceCached.getSignInCookies(securityToken); 
     String formDigestValue = serviceCached.getFormDigestValue(cookies); 
     MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); 
     headers.add("Cookie", Joiner.on(';').join(cookies)); 
     headers.add("Content-type", "application/json;odata=verbose"); 
     if (isWithDigest) { 
      headers.add("X-RequestDigest", formDigestValue); 
     } 
     if (isUpdate) { 
      headers.add("X-HTTP-Method", "MERGE"); 
      headers.add("IF-MATCH", "*"); 
     } 
     RequestEntity<String> requestEntity = new RequestEntity<>(json, headers, HttpMethod.POST, new URI(path)); 
     ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class); 
     String responseBody = responseEntity.getBody(); 
     log.debug(responseBody); 
     return responseBody; 
    } 

    public String attachFile(String path, byte[] file) throws Exception { 
     Long executionDateTime = serviceCached.parseExecutionDateTime(new Date()); 
     String securityToken = serviceCached.receiveSecurityToken(executionDateTime); 
     List<String> cookies = serviceCached.getSignInCookies(securityToken); 
     String formDigestValue = serviceCached.getFormDigestValue(cookies); 
     MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); 
     headers.add("Cookie", Joiner.on(';').join(cookies)); 
     headers.add("X-RequestDigest", formDigestValue); 
     headers.add("content-length", String.valueOf(file.length)); 
     RequestEntity<byte[]> requestEntity = new RequestEntity<>(file, headers, HttpMethod.POST, new URI(path)); 
     ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class); 
     String responseBody = responseEntity.getBody(); 
     log.debug(responseBody); 
     return responseBody; 
    } 

} 

XPathExpressionFactoryBeanの構成:

package com.waveaccess.someproject.commons.config; 

import com.waveaccess.someproject.commons.config.properties.SharePointProperties; 
import org.springframework.boot.context.properties.EnableConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.xml.xpath.XPathExpressionFactoryBean; 

import java.util.HashMap; 
import java.util.Map; 

/** 
* @author Maksim Kanev 
*/ 
@Configuration 
@EnableConfigurationProperties({SharePointProperties.class}) 
public class SharePointConfiguration { 

    @Bean 
    public XPathExpressionFactoryBean securityTokenExpressionFactoryBean() { 
     XPathExpressionFactoryBean xPathExpressionFactoryBean = new XPathExpressionFactoryBean(); 
     xPathExpressionFactoryBean.setExpression("/S:Envelope/S:Body/wst:RequestSecurityTokenResponse/wst:RequestedSecurityToken/wsse:BinarySecurityToken"); 

     Map<String, String> namespaces = new HashMap<>(); 
     namespaces.put("S", "http://www.w3.org/2003/05/soap-envelope"); 
     namespaces.put("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
     namespaces.put("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 
     namespaces.put("wsa", "http://www.w3.org/2005/08/addressing"); 
     namespaces.put("wst", "http://schemas.xmlsoap.org/ws/2005/02/trust"); 
     xPathExpressionFactoryBean.setNamespaces(namespaces); 
     return xPathExpressionFactoryBean; 
    } 
} 

最後にSharePointProperties

package com.waveaccess.someproject.commons.config.properties; 

import org.springframework.boot.context.properties.ConfigurationProperties; 

/** 
* @author Maksim Kanev 
*/ 
@ConfigurationProperties("sharepoint") 
public class SharePointProperties { 

    private String username; 
    private String password; 

    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 
} 
+0

返信ありがとうございます。次のコードを実行するためのxPathExpressionの実装String SecurityToken = xPathExpression.evaluateAsString(definitionDocument); – Anand

+0

@Anand this one http://docs.spring.io/spring-ws/site/apidocs/org/springframework/xml/xpath/XPathExpression.html – Maksim

+0

それぞれのfactoryBeanを追加しましたが、その値はわかりませんプロパティ 'namespace.base'。プロパティの値を教えてください。また、responseEntityオブジェクトの出力は「認証に失敗しました - 入力して保存したパスワードが一致しません」 – Anand

関連する問題