Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尽管我使用了正确的OAuth令牌,但尝试从Java应用程序访问托管的SharePoint 2013给了我401_Java_Rest_Oauth_Sharepoint 2013_Ntlm - Fatal编程技术网

尽管我使用了正确的OAuth令牌,但尝试从Java应用程序访问托管的SharePoint 2013给了我401

尽管我使用了正确的OAuth令牌,但尝试从Java应用程序访问托管的SharePoint 2013给了我401,java,rest,oauth,sharepoint-2013,ntlm,Java,Rest,Oauth,Sharepoint 2013,Ntlm,我正在尝试使用小型Java web应用程序访问我们公司的SharePoint 2013实例,该实例位于ourinstance.SharePoint.com 我通过以下方式通过_layouts/15/AppRegNew.aspx注册了应用程序: 我让SP生成客户端ID、客户端机密、 至我设置的应用程序域:ourdomain:8443 要重定向我设置的URL:https://ourdomain:8443/our-重定向处理 我使用_layouts/15/appinv.aspx编辑了应用程序权限,在这

我正在尝试使用小型Java web应用程序访问我们公司的SharePoint 2013实例,该实例位于ourinstance.SharePoint.com

我通过以下方式通过_layouts/15/AppRegNew.aspx注册了应用程序:

  • 我让SP生成客户端ID、客户端机密、
  • 至我设置的应用程序域:ourdomain:8443
  • 要重定向我设置的URL:
    https://ourdomain:8443/our-重定向处理
  • 我使用_layouts/15/appinv.aspx编辑了应用程序权限,在这里我按客户端ID查找它,并编辑了它的权限请求XML,以包含:

    <AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest Scope="http://insideidc.sharepoint.com/oursite/web" Right="FullControl"/>
    </AppPermissionRequests>
    
    它使用com.google.api.client。auth、http和json类

    我在REST调用此URL时使用的令牌:

    https://ourinstance.sharepoint.com/oursite/_api/web/getFolderByServerRelativeUrl('/thefolderIwant')/Files
    
    使用以下标题:

    Accept: application/json;odata=verbose
    Authorization: Bearer theToken
    
    响应要求我登录,而响应头设置了WWW-Authenticate:NTLM

    第一个问题:获取OAuth令牌的复杂过程是否应该以另一个凭据请求结束


    第二个也是主要的问题:当SharePoint为我们托管时,我如何为NTLM Authenticator构建域\用户名?我在尝试访问Microsoft的Project Online时也有类似的经历。 我发现了一些有用的信息,这些信息为我指明了正确的方向。他建议用提琴手嗅包。一旦我这样做了,我看到了实际发生的事情。 下面是我用来解决这个问题的一些Java代码,使用Apache的HttpClient、Apache的common io和log4j来解决这个问题:

    /**
    
        This is for using Java to connect with Microsoft's Project Online
    
        If you go into your Project Online, go to 'Server Settings' -> 'Manage Users', and look under the column 'User Logon Account'
    
        If it looks like :
            i:0#.w|domain\\username
        then you can just scroll down to where I call 
    
                    httpclient.getCredentialsProvider().setCredentials(
                            new AuthScope(url.getHost(), url.getPort(), AuthScope.ANY_REALM, AuthScope.ANY_SCHEME),
                            new NTCredentials(
                                    USERNAME,
                                    PASSWORD,
                                    url.getHost(), 
                                    DOMAIN));
    
    
        However, if it looks more like :
            i:0#.f|membership|username@yourcompany.com
        then you'll need to use OAuth, which is what this file demonstrates.
    
    */
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.StringWriter;
    import java.io.UnsupportedEncodingException;
    import java.net.URL;
    import java.nio.charset.StandardCharsets;
    import java.util.Calendar;
    import java.util.UUID;
    
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.apache.commons.io.IOUtils;// from commons-io-2.4.jar
    import org.apache.http.Header;// from httpcore-4.2.4.jar
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.NTCredentials;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.log4j.Logger;// from log4j.jar
    import org.w3c.dom.Document;
    import org.xml.sax.SAXException;
    
    public class ProjectOnline {
    
        private static final Logger logger         = Logger.getLogger(ProjectOnline.class);
    
        private static final String USERNAME       = "your user's email address";
        private static final String PASSWORD       = "password";
        private static final String DOMAIN         = "YOURDOMAIN";
        private static final String PROJECT_SERVER = "https://your.project.online.sharepoint.com";
        private static final String EMAIL_DOMAIN   = "@your.company.com";
    
    
        public static void main(String[] args) {
    
            ProjectOnline dao = new ProjectOnline();
            System.out.println(dao.getOAuthCookie());
    
        }
    
        private boolean needToUseOAuth(String username) {
            if (username == null) return false;
            return username.toLowerCase().endsWith(EMAIL_DOMAIN.toLowerCase());
        }
    
        public String getOAuthCookie() {
    
            if (needToUseOAuth(USERNAME)) {
    
                String samlSecurityToken = postLoginCredentialsToOurOAuthService();
    
                if (samlSecurityToken != null && samlSecurityToken.isEmpty() == false) {
    
                    String binarySecurityToken = postSamlSecurityTokenToSecondSite(samlSecurityToken);
    
                    if (binarySecurityToken != null && binarySecurityToken.isEmpty() == false) {
    
                        String spoidcrlCookie = getSpoidcrlCookie(binarySecurityToken);
                        return spoidcrlCookie;
                    } else {
                        //System.out.println("getXMLDocument - OAuth authentication / authorization failed : Binary Security Token was not found");
                        logger.error("getOAuthCookie - OAuth authentication / authorization failed : Binary Security Token was not found");
                    }
                } else {
                    //System.out.println("getXMLDocument - OAuth authentication / authorization failed : SAML Security Token was not found");
                    logger.error("getOAuthCookie - OAuth authentication / authorization failed : SAML Security Token was not found");
                }
            }
    
            return "";
        }
    
        // Step 1 - Find the URL to your company's OAuth site
        private String getOurOAuthServerURL(String emailAddress) {
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            // Go to this site, passing in email address. Should tell the URL for your company's OAuth site
            HttpPost httppost = new HttpPost("https://login.microsoftonline.com/GetUserRealm.srf?xml=1&login=" + emailAddress);
    
            try {
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("getOurOAuthServerURL - status = " + status);
                logger.info("getOurOAuthServerURL - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    String ourAuthURL = getSTSAuthURL(xml);
                    //System.out.println("ourAuthURL = " + ourAuthURL);
                    return ourAuthURL;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
            return "";
        }
    
        private String getBinarySecurityToken(String xml) {
            return getValuesBetweenTags(xml, "<wsse:BinarySecurityToken Id=\"Compact0\">", "</wsse:BinarySecurityToken>");
        }
    
        private String getSTSAuthURL(String xml) {
            return getValuesBetweenTags(xml, "<STSAuthURL>", "</STSAuthURL>");
        }
    
        private String getSamlSecurityToken(String xml) {
            return getValuesBetweenTags(xml, "<t:RequestedSecurityToken>", "</t:RequestedSecurityToken>");
        }
    
        private String getValuesBetweenTags(String xml, String tagToLeft, String tagToRight) {
            if (xml == null || xml.isEmpty()) return "";
    
            int startToken = xml.indexOf(tagToLeft);
            if (startToken > -1) {
                return xml.substring(startToken + tagToLeft.length(), xml.indexOf(tagToRight, startToken));
            } else {
                return "";
            }
        }
    
        private String getTimeString(int minutesInFuture) {
            Calendar rightNow = Calendar.getInstance();
            rightNow.add(Calendar.SECOND, (((rightNow.get(Calendar.ZONE_OFFSET) + (rightNow.get(Calendar.DST_OFFSET)))/-1000)));
            rightNow.add(Calendar.MINUTE, minutesInFuture);
            String timeString = String.format("%d-%02d-%02dT%02d:%02d:%02d.0000000Z", 
                                         rightNow.get(Calendar.YEAR), 
                                        (rightNow.get(Calendar.MONTH) + 1), 
                                         rightNow.get(Calendar.DATE), 
                                         rightNow.get(Calendar.HOUR_OF_DAY),
                                         rightNow.get(Calendar.MINUTE),
                                         rightNow.get(Calendar.SECOND));
            return timeString;
        }
    
        // Step 2 - POST an XML message, with a few key fields filled in (rest can be left as-is)
        // This should be sent to your company's OAuth site
        private String postLoginCredentialsToOurOAuthService() {
    
            String ourOAuthService = getOurOAuthServerURL(USERNAME);
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            StringBuilder xmlString = new StringBuilder();
    
            xmlString.append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" ");
            xmlString.append("xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"  ");
            xmlString.append("xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\"  ");
            xmlString.append("xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\"  ");
            xmlString.append("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"  ");
            xmlString.append("xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"  ");
            xmlString.append("xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2005/02/sc\"  ");
            xmlString.append("xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\"> ");
            xmlString.append("<s:Header> ");
            xmlString.append("<wsa:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action> ");
            xmlString.append("<wsa:To s:mustUnderstand=\"1\">" + ourOAuthService + "</wsa:To> ");
            xmlString.append("<wsa:MessageID>").append(UUID.randomUUID().toString()).append("</wsa:MessageID> ");
            xmlString.append("<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\"> ");
            xmlString.append("<ps:HostingApp>Managed IDCRL</ps:HostingApp> ");
            xmlString.append("<ps:BinaryVersion>6</ps:BinaryVersion> ");
            xmlString.append("<ps:UIVersion>1</ps:UIVersion> ");
            xmlString.append("<ps:Cookies></ps:Cookies> ");
            xmlString.append("<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams> ");
            xmlString.append("</ps:AuthInfo> ");
            xmlString.append("<wsse:Security> ");
            xmlString.append("<wsse:UsernameToken wsu:Id=\"user\"> ");
            xmlString.append("<wsse:Username>").append(USERNAME).append("</wsse:Username> ");
            xmlString.append("<wsse:Password>").append(PASSWORD).append("</wsse:Password> ");
            xmlString.append("</wsse:UsernameToken> ");
            xmlString.append("<wsu:Timestamp Id=\"Timestamp\"> ");
            xmlString.append("<wsu:Created>" + getTimeString(0) + "</wsu:Created> ");
            xmlString.append("<wsu:Expires>" + getTimeString(10) + "</wsu:Expires> ");
            xmlString.append("</wsu:Timestamp> ");
            xmlString.append("</wsse:Security> ");
            xmlString.append("</s:Header> ");
            xmlString.append("<s:Body> ");
            xmlString.append("<wst:RequestSecurityToken Id=\"RST0\"> ");
            xmlString.append("<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType> ");
            xmlString.append("<wsp:AppliesTo> ");
            xmlString.append("<wsa:EndpointReference> ");
            xmlString.append("<wsa:Address>urn:federation:MicrosoftOnline</wsa:Address> ");
            xmlString.append("</wsa:EndpointReference> ");
            xmlString.append("</wsp:AppliesTo> ");
            xmlString.append("<wst:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</wst:KeyType> ");
            xmlString.append("</wst:RequestSecurityToken> ");
            xmlString.append("</s:Body> ");
            xmlString.append("</s:Envelope> ");
    
            HttpPost httppost = new HttpPost(ourOAuthService);
    
            try {
    
                httppost.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
    
                httppost.setEntity(new StringEntity(xmlString.toString()));// Set this in the body
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("postLoginCredentialsToOurOAuthService - status = " + status);
                logger.info("postLoginCredentialsToOurOAuthService - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    // Now, extract out the SAML Security Token. It is several lines (~49, if you parse it out).
                    String samlSecurityToken = getSamlSecurityToken(xml);
                    //System.out.println("samlSecurityToken = " + samlSecurityToken);
                    return samlSecurityToken;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
            return "";
        }
    
        // Step 3 - Now that you have the SAML Security Token, you embed it within some other generic XML, and send back to Microsoft server
        private String postSamlSecurityTokenToSecondSite(String samlSecurityToken) {
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            try {
    
                HttpPost httppost = new HttpPost("https://login.microsoftonline.com/rst2.srf");
    
                httppost.addHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)");
    
                StringBuilder xmlString = new StringBuilder();
    
                xmlString.append("<S:Envelope xmlns:S=\"http://www.w3.org/2003/05/soap-envelope\" ");
                xmlString.append("xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" ");
                xmlString.append("xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\" ");
                xmlString.append("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" ");
                xmlString.append("xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" ");
                xmlString.append("xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">");
                xmlString.append("<S:Header>");
                xmlString.append("<wsa:Action S:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>");
                xmlString.append("<wsa:To S:mustUnderstand=\"1\">https://login.microsoftonline.com/rst2.srf</wsa:To>");
                xmlString.append("<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/LiveID/SoapServices/v1\" Id=\"PPAuthInfo\">");
                xmlString.append("<ps:BinaryVersion>5</ps:BinaryVersion>");
                xmlString.append("<ps:HostingApp>Managed IDCRL</ps:HostingApp>");
                xmlString.append("</ps:AuthInfo>");
                xmlString.append("<wsse:Security>");
                xmlString.append(samlSecurityToken);
                xmlString.append("</wsse:Security>");
                xmlString.append("</S:Header>");
                xmlString.append("<S:Body>");
                xmlString.append("<wst:RequestSecurityToken xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\" Id=\"RST0\">");
                xmlString.append("<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>");
                xmlString.append("<wsp:AppliesTo>");
                xmlString.append("<wsa:EndpointReference>");
                xmlString.append("<wsa:Address>sharepoint.com</wsa:Address>");
                xmlString.append("</wsa:EndpointReference>");
                xmlString.append("</wsp:AppliesTo>");
                xmlString.append("<wsp:PolicyReference URI=\"MBI\"></wsp:PolicyReference>");
                xmlString.append("</wst:RequestSecurityToken>");
                xmlString.append("</S:Body>");
                xmlString.append("</S:Envelope>");
    
                httppost.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
    
                httppost.setEntity(new StringEntity(xmlString.toString()));
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("postSamlSecurityTokenToSecondSite - status = " + status);
                logger.info("postSamlSecurityTokenToSecondSite - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    // Extract out the value from just one, single line of this returned XML file
                    String binarySecurityToken = getBinarySecurityToken(xml);
                    //System.out.println("binarySecurityToken = " + binarySecurityToken);
                    return binarySecurityToken;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
    
            return "";
        }
    
        // Step 4 - Using the extracted value, the Binary Security Token, build a header, and add it to the next request
        // This will go to your own Project Online server, which should return back a reply message, containing a 'Set-Cookie' cookie with 'SPOIDCRL' in the value
        private String getSpoidcrlCookie(String binarySecurityToken) {
            try {
    
                HttpGet httpget = new HttpGet(PROJECT_SERVER + "/_vti_bin/idcrl.svc/");
    
                httpget.addHeader("Authorization", "BPOSIDCRL " + binarySecurityToken);
    
                DefaultHttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = httpclient.execute(httpget);
    
                String status = response.getStatusLine().toString();
                //System.out.println("getSpoidcrlCookie - status = " + status);
                logger.info("getSpoidcrlCookie - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if ("HTTP/1.1 200 OK".equals(status)) {
    
                    Header[] headers = response.getHeaders("Set-Cookie");
                    for (Header header : headers) {
                        if (header.getValue().contains("SPOIDCRL")) {
                            String spoidcrlCookie = header.getValue();
                            //System.out.println("Found SPOIDCRL cookie : " + spoidcrlCookie);
                            return spoidcrlCookie;
                        }
                    }
                }
            } catch (ClientProtocolException e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (Exception e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            }
            return null;
        }
    
        public Document getXMLDocument(String strURL) {
    
            String spoidcrlCookie = getOAuthCookie();
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            HttpGet httpget = new HttpGet(strURL);
    
            try {
    
                URL url = new URL(strURL);
    
                if (needToUseOAuth(USERNAME)) {
    
                    httpget.addHeader("Cookie", spoidcrlCookie);
    
                } else {
    
                    // Otherwise, can just use this simple way of logging in, using the Domain
                    httpclient.getCredentialsProvider().setCredentials(
                            new AuthScope(url.getHost(), url.getPort(), AuthScope.ANY_REALM, AuthScope.ANY_SCHEME),
                            new NTCredentials(
                                    USERNAME,
                                    PASSWORD,
                                    url.getHost(), 
                                    DOMAIN));
    
                }
    
                //System.out.println("getXMLDocument - strURL " + strURL);
                //logger.info("getXMLDocument - strURL " + strURL);
                //logger.info("getXMLDocument - executing request " + httpget.getRequestLine());
                HttpResponse response = httpclient.execute(httpget);//httppost
                HttpEntity entity = response.getEntity();
    
                //logger.info("getXMLDocument - ----------------------------------------");
                //for (Header header : response.getAllHeaders()) {
                //  System.out.println("getXMLDocument - header = " + header.toString());
                //}
                String status = response.getStatusLine().toString();
                //System.out.println("getXMLDocument - status = " + status);
                //logger.info("getXMLDocument - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    if (xml.endsWith("</feed>") == false) {
                        //logger.warn("The XML did not end with </feed>");
                        xml = xml + "</feed>";
                    }
    
                    InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
                    Document doc = docBuilder.parse(inputStream);
                    return doc;
    
                } else {
    
                    logger.error("getXMLDocument - status = " + status);
    
                }
    
            } catch (ClientProtocolException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ParserConfigurationException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (SAXException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (Exception e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
    
            logger.warn("Exiting from getXMLDocument but returning null");
            return null;
        }
    }
    
    /**
    这是为了使用Java与Microsoft的Project Online连接
    如果您联机进入项目,请转到“服务器设置”->“管理用户”,然后在“用户登录帐户”列下查看
    如果它看起来像:
    i:0#.w |域\\用户名
    然后你可以向下滚动到我呼叫的地方
    httpclient.getCredentialsProvider().setCredentials(
    新的AuthScope(url.getHost()、url.getPort()、AuthScope.ANY\u领域、AuthScope.ANY\u方案),
    新NTC证书(
    用户名,
    密码,
    url.getHost(),
    域);
    但是,如果它看起来更像:
    i:0.f成员资格|username@yourcompany.com
    然后您将需要使用OAuth,这就是这个文件所演示的。
    */
    导入java.io.ByteArrayInputStream;
    导入java.io.IOException;
    导入java.io.InputStream;
    导入java.io.StringWriter;
    导入java.io.UnsupportedEncodingException;
    导入java.net.URL;
    导入java.nio.charset.StandardCharset;
    导入java.util.Calendar;
    导入java.util.UUID;
    导入javax.xml.parsers.DocumentBuilder;
    导入javax.xml.parsers.DocumentBuilderFactory;
    导入javax.xml.parsers.parserConfiguration异常;
    导入org.apache.commons.io.IOUtils;//来自commons-io-2.4.jar
    导入org.apache.http.Header;//来自httpcore-4.2.4.jar
    导入org.apache.http.HttpEntity;
    导入org.apache.http.HttpResponse;
    导入org.apache.http.auth.AuthScope;
    导入org.apache.http.auth.NTCredentials;
    导入org.apache.http.client.ClientProtocolException;
    导入org.apache.http.client.methods.HttpGet;
    导入org.apache.http.client.methods.HttpPost;
    导入org.apache.http.entity.StringEntity;
    导入org.apache.http.impl.client.DefaultHttpClient;
    导入org.apache.log4j.Logger;//来自log4j.jar
    导入org.w3c.dom.Document;
    导入org.xml.sax.SAXException;
    公共课项目在线{
    私有静态最终记录器=Logger.getLogger(ProjectOnline.class);
    私有静态最终字符串USERNAME=“您用户的电子邮件地址”;
    私有静态最终字符串PASSWORD=“PASSWORD”;
    私有静态最终字符串DOMAIN=“YOURDOMAIN”;
    私有静态最终字符串项目\u服务器=”https://your.project.online.sharepoint.com";
    私有静态最终字符串EMAIL_DOMAIN=“@your.company.com”;
    公共静态void main(字符串[]args){
    ProjectOnline dao=新建ProjectOnline();
    System.out.println(dao.getOAuthCookie());
    }
    私有布尔NeedToUserAuth(字符串用户名){
    如果(username==null)返回false;
    返回username.toLowerCase().endsWith(EMAIL_DOMAIN.toLowerCase());
    }
    公共字符串getOAuthCookie(){
    if(needToUserAuth(用户名)){
    字符串samlSecurityToken=postlogincredentialstoourauthservice();
    if(samlSecurityToken!=null&&samlSecurityToken.isEmpty()==false){
    String binarySecurityToken=postSamlSecurityTokenToSecondSite(samlSecurityToken);
    if(binarySecurityToken!=null&&binarySecurityToken.isEmpty()==false){
    字符串spoidcrlocokie=getspoidcrlocokie(二进制安全令牌);
    返回spoidcrlocokie;
    }否则{
    //System.out.println(“getXMLDocument-OAuth身份验证/授权失败:未找到二进制安全令牌”);
    错误(“getOAuthCookie-OAuth身份验证/授权失败:未找到二进制安全令牌”);
    }
    }否则{
    //System.out.println(“getXMLDocument-OAuth身份验证/授权失败:未找到SAML安全令牌”);
    错误(“getOAuthCookie-OAuth身份验证/授权失败:未找到SAML安全令牌”);
    }
    }
    返回“”;
    }
    //第1步-找到公司OAuth站点的URL
    私有字符串getOurOAuthServerURL(字符串电子邮件地址){
    DefaultHttpClient httpclient=新的DefaultHttpClient();
    //转到此网站,输入电子邮件地址。应该告诉您公司的OAuth网站的URL
    HttpPost HttpPost=新的HttpPost(“https://login.microsoftonline.com/GetUserRealm.srf?xml=1&login=“+电子邮件地址);
    试一试{
    HttpResponse响应
    
    /**
    
        This is for using Java to connect with Microsoft's Project Online
    
        If you go into your Project Online, go to 'Server Settings' -> 'Manage Users', and look under the column 'User Logon Account'
    
        If it looks like :
            i:0#.w|domain\\username
        then you can just scroll down to where I call 
    
                    httpclient.getCredentialsProvider().setCredentials(
                            new AuthScope(url.getHost(), url.getPort(), AuthScope.ANY_REALM, AuthScope.ANY_SCHEME),
                            new NTCredentials(
                                    USERNAME,
                                    PASSWORD,
                                    url.getHost(), 
                                    DOMAIN));
    
    
        However, if it looks more like :
            i:0#.f|membership|username@yourcompany.com
        then you'll need to use OAuth, which is what this file demonstrates.
    
    */
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.StringWriter;
    import java.io.UnsupportedEncodingException;
    import java.net.URL;
    import java.nio.charset.StandardCharsets;
    import java.util.Calendar;
    import java.util.UUID;
    
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.apache.commons.io.IOUtils;// from commons-io-2.4.jar
    import org.apache.http.Header;// from httpcore-4.2.4.jar
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.NTCredentials;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.log4j.Logger;// from log4j.jar
    import org.w3c.dom.Document;
    import org.xml.sax.SAXException;
    
    public class ProjectOnline {
    
        private static final Logger logger         = Logger.getLogger(ProjectOnline.class);
    
        private static final String USERNAME       = "your user's email address";
        private static final String PASSWORD       = "password";
        private static final String DOMAIN         = "YOURDOMAIN";
        private static final String PROJECT_SERVER = "https://your.project.online.sharepoint.com";
        private static final String EMAIL_DOMAIN   = "@your.company.com";
    
    
        public static void main(String[] args) {
    
            ProjectOnline dao = new ProjectOnline();
            System.out.println(dao.getOAuthCookie());
    
        }
    
        private boolean needToUseOAuth(String username) {
            if (username == null) return false;
            return username.toLowerCase().endsWith(EMAIL_DOMAIN.toLowerCase());
        }
    
        public String getOAuthCookie() {
    
            if (needToUseOAuth(USERNAME)) {
    
                String samlSecurityToken = postLoginCredentialsToOurOAuthService();
    
                if (samlSecurityToken != null && samlSecurityToken.isEmpty() == false) {
    
                    String binarySecurityToken = postSamlSecurityTokenToSecondSite(samlSecurityToken);
    
                    if (binarySecurityToken != null && binarySecurityToken.isEmpty() == false) {
    
                        String spoidcrlCookie = getSpoidcrlCookie(binarySecurityToken);
                        return spoidcrlCookie;
                    } else {
                        //System.out.println("getXMLDocument - OAuth authentication / authorization failed : Binary Security Token was not found");
                        logger.error("getOAuthCookie - OAuth authentication / authorization failed : Binary Security Token was not found");
                    }
                } else {
                    //System.out.println("getXMLDocument - OAuth authentication / authorization failed : SAML Security Token was not found");
                    logger.error("getOAuthCookie - OAuth authentication / authorization failed : SAML Security Token was not found");
                }
            }
    
            return "";
        }
    
        // Step 1 - Find the URL to your company's OAuth site
        private String getOurOAuthServerURL(String emailAddress) {
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            // Go to this site, passing in email address. Should tell the URL for your company's OAuth site
            HttpPost httppost = new HttpPost("https://login.microsoftonline.com/GetUserRealm.srf?xml=1&login=" + emailAddress);
    
            try {
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("getOurOAuthServerURL - status = " + status);
                logger.info("getOurOAuthServerURL - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    String ourAuthURL = getSTSAuthURL(xml);
                    //System.out.println("ourAuthURL = " + ourAuthURL);
                    return ourAuthURL;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getOurOAuthServerURL ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
            return "";
        }
    
        private String getBinarySecurityToken(String xml) {
            return getValuesBetweenTags(xml, "<wsse:BinarySecurityToken Id=\"Compact0\">", "</wsse:BinarySecurityToken>");
        }
    
        private String getSTSAuthURL(String xml) {
            return getValuesBetweenTags(xml, "<STSAuthURL>", "</STSAuthURL>");
        }
    
        private String getSamlSecurityToken(String xml) {
            return getValuesBetweenTags(xml, "<t:RequestedSecurityToken>", "</t:RequestedSecurityToken>");
        }
    
        private String getValuesBetweenTags(String xml, String tagToLeft, String tagToRight) {
            if (xml == null || xml.isEmpty()) return "";
    
            int startToken = xml.indexOf(tagToLeft);
            if (startToken > -1) {
                return xml.substring(startToken + tagToLeft.length(), xml.indexOf(tagToRight, startToken));
            } else {
                return "";
            }
        }
    
        private String getTimeString(int minutesInFuture) {
            Calendar rightNow = Calendar.getInstance();
            rightNow.add(Calendar.SECOND, (((rightNow.get(Calendar.ZONE_OFFSET) + (rightNow.get(Calendar.DST_OFFSET)))/-1000)));
            rightNow.add(Calendar.MINUTE, minutesInFuture);
            String timeString = String.format("%d-%02d-%02dT%02d:%02d:%02d.0000000Z", 
                                         rightNow.get(Calendar.YEAR), 
                                        (rightNow.get(Calendar.MONTH) + 1), 
                                         rightNow.get(Calendar.DATE), 
                                         rightNow.get(Calendar.HOUR_OF_DAY),
                                         rightNow.get(Calendar.MINUTE),
                                         rightNow.get(Calendar.SECOND));
            return timeString;
        }
    
        // Step 2 - POST an XML message, with a few key fields filled in (rest can be left as-is)
        // This should be sent to your company's OAuth site
        private String postLoginCredentialsToOurOAuthService() {
    
            String ourOAuthService = getOurOAuthServerURL(USERNAME);
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            StringBuilder xmlString = new StringBuilder();
    
            xmlString.append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" ");
            xmlString.append("xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"  ");
            xmlString.append("xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\"  ");
            xmlString.append("xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\"  ");
            xmlString.append("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"  ");
            xmlString.append("xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"  ");
            xmlString.append("xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2005/02/sc\"  ");
            xmlString.append("xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\"> ");
            xmlString.append("<s:Header> ");
            xmlString.append("<wsa:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action> ");
            xmlString.append("<wsa:To s:mustUnderstand=\"1\">" + ourOAuthService + "</wsa:To> ");
            xmlString.append("<wsa:MessageID>").append(UUID.randomUUID().toString()).append("</wsa:MessageID> ");
            xmlString.append("<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\"> ");
            xmlString.append("<ps:HostingApp>Managed IDCRL</ps:HostingApp> ");
            xmlString.append("<ps:BinaryVersion>6</ps:BinaryVersion> ");
            xmlString.append("<ps:UIVersion>1</ps:UIVersion> ");
            xmlString.append("<ps:Cookies></ps:Cookies> ");
            xmlString.append("<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams> ");
            xmlString.append("</ps:AuthInfo> ");
            xmlString.append("<wsse:Security> ");
            xmlString.append("<wsse:UsernameToken wsu:Id=\"user\"> ");
            xmlString.append("<wsse:Username>").append(USERNAME).append("</wsse:Username> ");
            xmlString.append("<wsse:Password>").append(PASSWORD).append("</wsse:Password> ");
            xmlString.append("</wsse:UsernameToken> ");
            xmlString.append("<wsu:Timestamp Id=\"Timestamp\"> ");
            xmlString.append("<wsu:Created>" + getTimeString(0) + "</wsu:Created> ");
            xmlString.append("<wsu:Expires>" + getTimeString(10) + "</wsu:Expires> ");
            xmlString.append("</wsu:Timestamp> ");
            xmlString.append("</wsse:Security> ");
            xmlString.append("</s:Header> ");
            xmlString.append("<s:Body> ");
            xmlString.append("<wst:RequestSecurityToken Id=\"RST0\"> ");
            xmlString.append("<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType> ");
            xmlString.append("<wsp:AppliesTo> ");
            xmlString.append("<wsa:EndpointReference> ");
            xmlString.append("<wsa:Address>urn:federation:MicrosoftOnline</wsa:Address> ");
            xmlString.append("</wsa:EndpointReference> ");
            xmlString.append("</wsp:AppliesTo> ");
            xmlString.append("<wst:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</wst:KeyType> ");
            xmlString.append("</wst:RequestSecurityToken> ");
            xmlString.append("</s:Body> ");
            xmlString.append("</s:Envelope> ");
    
            HttpPost httppost = new HttpPost(ourOAuthService);
    
            try {
    
                httppost.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
    
                httppost.setEntity(new StringEntity(xmlString.toString()));// Set this in the body
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("postLoginCredentialsToOurOAuthService - status = " + status);
                logger.info("postLoginCredentialsToOurOAuthService - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    // Now, extract out the SAML Security Token. It is several lines (~49, if you parse it out).
                    String samlSecurityToken = getSamlSecurityToken(xml);
                    //System.out.println("samlSecurityToken = " + samlSecurityToken);
                    return samlSecurityToken;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("postLoginCredentialsToOurOAuthService ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
            return "";
        }
    
        // Step 3 - Now that you have the SAML Security Token, you embed it within some other generic XML, and send back to Microsoft server
        private String postSamlSecurityTokenToSecondSite(String samlSecurityToken) {
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            try {
    
                HttpPost httppost = new HttpPost("https://login.microsoftonline.com/rst2.srf");
    
                httppost.addHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)");
    
                StringBuilder xmlString = new StringBuilder();
    
                xmlString.append("<S:Envelope xmlns:S=\"http://www.w3.org/2003/05/soap-envelope\" ");
                xmlString.append("xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" ");
                xmlString.append("xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\" ");
                xmlString.append("xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" ");
                xmlString.append("xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" ");
                xmlString.append("xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">");
                xmlString.append("<S:Header>");
                xmlString.append("<wsa:Action S:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>");
                xmlString.append("<wsa:To S:mustUnderstand=\"1\">https://login.microsoftonline.com/rst2.srf</wsa:To>");
                xmlString.append("<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/LiveID/SoapServices/v1\" Id=\"PPAuthInfo\">");
                xmlString.append("<ps:BinaryVersion>5</ps:BinaryVersion>");
                xmlString.append("<ps:HostingApp>Managed IDCRL</ps:HostingApp>");
                xmlString.append("</ps:AuthInfo>");
                xmlString.append("<wsse:Security>");
                xmlString.append(samlSecurityToken);
                xmlString.append("</wsse:Security>");
                xmlString.append("</S:Header>");
                xmlString.append("<S:Body>");
                xmlString.append("<wst:RequestSecurityToken xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\" Id=\"RST0\">");
                xmlString.append("<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>");
                xmlString.append("<wsp:AppliesTo>");
                xmlString.append("<wsa:EndpointReference>");
                xmlString.append("<wsa:Address>sharepoint.com</wsa:Address>");
                xmlString.append("</wsa:EndpointReference>");
                xmlString.append("</wsp:AppliesTo>");
                xmlString.append("<wsp:PolicyReference URI=\"MBI\"></wsp:PolicyReference>");
                xmlString.append("</wst:RequestSecurityToken>");
                xmlString.append("</S:Body>");
                xmlString.append("</S:Envelope>");
    
                httppost.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
    
                httppost.setEntity(new StringEntity(xmlString.toString()));
    
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
    
                String status = response.getStatusLine().toString();
                //System.out.println("postSamlSecurityTokenToSecondSite - status = " + status);
                logger.info("postSamlSecurityTokenToSecondSite - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    // Extract out the value from just one, single line of this returned XML file
                    String binarySecurityToken = getBinarySecurityToken(xml);
                    //System.out.println("binarySecurityToken = " + binarySecurityToken);
                    return binarySecurityToken;
    
                }
            } catch (UnsupportedEncodingException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ClientProtocolException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("postSamlSecurityTokenToSecondSite ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
    
            return "";
        }
    
        // Step 4 - Using the extracted value, the Binary Security Token, build a header, and add it to the next request
        // This will go to your own Project Online server, which should return back a reply message, containing a 'Set-Cookie' cookie with 'SPOIDCRL' in the value
        private String getSpoidcrlCookie(String binarySecurityToken) {
            try {
    
                HttpGet httpget = new HttpGet(PROJECT_SERVER + "/_vti_bin/idcrl.svc/");
    
                httpget.addHeader("Authorization", "BPOSIDCRL " + binarySecurityToken);
    
                DefaultHttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = httpclient.execute(httpget);
    
                String status = response.getStatusLine().toString();
                //System.out.println("getSpoidcrlCookie - status = " + status);
                logger.info("getSpoidcrlCookie - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if ("HTTP/1.1 200 OK".equals(status)) {
    
                    Header[] headers = response.getHeaders("Set-Cookie");
                    for (Header header : headers) {
                        if (header.getValue().contains("SPOIDCRL")) {
                            String spoidcrlCookie = header.getValue();
                            //System.out.println("Found SPOIDCRL cookie : " + spoidcrlCookie);
                            return spoidcrlCookie;
                        }
                    }
                }
            } catch (ClientProtocolException e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (Exception e) {
                logger.error("getSpoidcrlCookie ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            }
            return null;
        }
    
        public Document getXMLDocument(String strURL) {
    
            String spoidcrlCookie = getOAuthCookie();
    
            DefaultHttpClient httpclient = new DefaultHttpClient();
    
            HttpGet httpget = new HttpGet(strURL);
    
            try {
    
                URL url = new URL(strURL);
    
                if (needToUseOAuth(USERNAME)) {
    
                    httpget.addHeader("Cookie", spoidcrlCookie);
    
                } else {
    
                    // Otherwise, can just use this simple way of logging in, using the Domain
                    httpclient.getCredentialsProvider().setCredentials(
                            new AuthScope(url.getHost(), url.getPort(), AuthScope.ANY_REALM, AuthScope.ANY_SCHEME),
                            new NTCredentials(
                                    USERNAME,
                                    PASSWORD,
                                    url.getHost(), 
                                    DOMAIN));
    
                }
    
                //System.out.println("getXMLDocument - strURL " + strURL);
                //logger.info("getXMLDocument - strURL " + strURL);
                //logger.info("getXMLDocument - executing request " + httpget.getRequestLine());
                HttpResponse response = httpclient.execute(httpget);//httppost
                HttpEntity entity = response.getEntity();
    
                //logger.info("getXMLDocument - ----------------------------------------");
                //for (Header header : response.getAllHeaders()) {
                //  System.out.println("getXMLDocument - header = " + header.toString());
                //}
                String status = response.getStatusLine().toString();
                //System.out.println("getXMLDocument - status = " + status);
                //logger.info("getXMLDocument - status = " + status);
    
                // If response status doesn't equal 'OK' then it didn't work.
                if (entity != null && "HTTP/1.1 200 OK".equals(status)) {
    
                    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    
                    StringWriter writer = new StringWriter();
                    IOUtils.copy(entity.getContent(), writer, "utf-8");
                    String xml = writer.toString();
    
                    //System.out.println(xml);
                    //logger.debug(xml);
    
                    if (xml.endsWith("</feed>") == false) {
                        //logger.warn("The XML did not end with </feed>");
                        xml = xml + "</feed>";
                    }
    
                    InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
                    Document doc = docBuilder.parse(inputStream);
                    return doc;
    
                } else {
    
                    logger.error("getXMLDocument - status = " + status);
    
                }
    
            } catch (ClientProtocolException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IOException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (ParserConfigurationException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (IllegalStateException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (SAXException e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } catch (Exception e) {
                logger.error("getXMLDocument ERROR | SHORT ERROR MESSAGE: " + e.getMessage() + " FULL ERROR MESSAGE: " + e.toString());
            } finally {
                // When HttpClient instance is no longer needed,
                // shut down the connection manager to ensure
                // immediate deallocation of all system resources
                httpclient.getConnectionManager().shutdown();
            }
    
            logger.warn("Exiting from getXMLDocument but returning null");
            return null;
        }
    }