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

こ雲淡風輕ζ 提交于 2021-02-20 03:51:26

问题


I am new to Azure and sharepoint integration with Java.

I am trying to integrate Java with Sharepoint. The Sharepoint-Office 365 is available in Azure ADFS. I need to write a Java program to authenticate and then access the files using the RESTful APIs provided by Sharepoint. Azure is using WS-Federation authentication process. I have been trying to look for the code that helps me to use the WS-F authentication and then access the files. I am not able to find any useful material.

The basic authentication is not working and I have nor worked in WS-F authentication. 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. For ex, the client ID is not required as the sharepoint is already available.

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.


回答1:


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:

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:

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


来源:https://stackoverflow.com/questions/40601341/access-office-365-sharepoint-rest-api-in-azure-using-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!