简体   繁体   English

使用Java在Azure中访问Office 365(SharePoint REST API)

[英]Access Office 365 (sharepoint REST api) in Azure using Java

I am new to Azure and sharepoint integration with Java. 我是Azure和SharePoint与Java集成的新手。

I am trying to integrate Java with Sharepoint. 我正在尝试将Java与Sharepoint集成。 The Sharepoint-Office 365 is available in Azure ADFS. Sharepoint-Office 365在Azure ADFS中可用。 I need to write a Java program to authenticate and then access the files using the RESTful APIs provided by Sharepoint. 我需要编写一个Java程序来进行身份验证,然后使用Sharepoint提供的RESTful API访问文件。 Azure is using WS-Federation authentication process. Azure正在使用WS-Federation身份验证过程。 I have been trying to look for the code that helps me to use the WS-F authentication and then access the files. 我一直在寻找可以帮助我使用WS-F身份验证然后访问文件的代码。 I am not able to find any useful material. 我找不到任何有用的材料。

The basic authentication is not working and I have nor worked in WS-F authentication. 基本认证不起作用,我也没有从事WS-F认证。 So no clue on where to start. 因此,不知道从哪里开始。 I also used the Office-365-sdk to do this, but could not do it as it is using the client ID and other attributes which are not relevant to my application. 我还使用Office-365-sdk来执行此操作,但是由于使用了与应用程序无关的客户端ID和其他属性,因此无法执行此操作。 For ex, the client ID is not required as the sharepoint is already available. 例如,由于共享点已可用,因此不需要客户端ID。

I got this link as well, but some of the methods are missing and it does not explain about the libraries used to achieve. 我也获得了此链接 ,但是缺少一些方法,并且没有解释用于实现的库。 Please guide me in implementing this. 请指导我实施此操作。

Here is a code from the article that you referred to: 这是您引用的文章中的代码:

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

}

Methods from this service should be called as follows: 此服务中的方法应如下调用:

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

}

Configuration of XPathExpressionFactoryBean : 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;
    }
}

And finally SharePointProperties : 最后是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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM