简体   繁体   中英

Authenticating Sharepoint site from background service and uploading file

I'm trying to authenticate up against Sharepoint so that it's possible for me to upload files onto a specific Sharepoint site.

I'm trying to use an X.509 certificate to retrieve the access token, but I keep getting (401): Unauthorized.

Here's the way I try to retrieve the access token with the certificate:

string authority = SettingsHelper.Authority;
string clientID = SettingsHelper.ClientId;
string serverName = SettingsHelper.SharepointServerName;
//Retreive the certificate path
string certFile = Server.MapPath(SettingsHelper.CertificatePath);
string certPassword = SettingsHelper.CertificatePassword;

AuthenticationResult authenticationResult = null;
AuthenticationContext authenticationContext = new AuthenticationContext(authority);

//Create the certificate file, using the path (certFile), password (certPassword) and the MachineKeySet
X509Certificate2 cert = new X509Certificate2(certFile, certPassword, X509KeyStorageFlags.MachineKeySet);

//Create the ClientAssertionCertificate using the clientID and the actual certificate
ClientAssertionCertificate cac = new ClientAssertionCertificate(clientID, cert);

//Retreive the access token using the serverName and client assertion
authenticationResult = authenticationContext.AcquireToken(serverName, cac);

And here's how I try to upload a specific file onto a specific Sharepoint list:

WebRequest request = null;
HttpWebResponse response = null;
byte[] bytesToUpload = bytes;
var returnValue = "";

string requestUriString = string.Format("{0}/_api/web/GetFolderByServerRelativeUrl(@sru)/Files/Add(url=@fn,overwrite=true)?@sru='{1}'&@fn='{2}'", url, HttpUtility.UrlEncode(serverRelativeUrl), HttpUtility.UrlEncode(fileName));

request = (HttpWebRequest)HttpWebRequest.Create(requestUriString);

request.Method = "POST";
(request as HttpWebRequest).Accept = "*/*";
request.ContentType = "application/json;odata=verbose";
request.Headers.Add("Authorization", String.Format("Bearer {0}", authenticationResult.AccessToken));
request.ContentLength = bytesToUpload.Length;


// Write the local file to the remote system
using (Stream requestStream = request.GetRequestStream())
{
    BinaryWriter writer = new BinaryWriter(requestStream);
    writer.Write(bytesToUpload, 0, bytesToUpload.Length);
    writer.Close();
}
// Get a web response back
response = (HttpWebResponse)request.GetResponse();

using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default))
{
    returnValue = sr.ReadToEnd();
    sr.Close();
}

if (request.RequestUri.ToString().Contains("GetFolderByServerRelativeUrl") == true)
{
    returnValue = "";
}

Some of the variables comes from the parameters:

 UploadEmail(System.IO.File.ReadAllBytes(emlFilePath), "https://(blablabla).sharepoint.com", "sites/(bla)/(bla)/Emails", email.Subject + ".msg");

I'm not sure what's wrong, and I'm definitely not sure how to fix this.

NOTE: Please don't tell me to use NetworkCredentials , I'd rather use the certificate or something else, but not NetworkCredentials

EDIT

Managed to debug the code and find this in the response header of the WebRequest :

在此输入图像描述

The better approach would be using the SharePoint Client Side Object Model (as hbulens suggested in comments). Here's the code that uploads the file to the library in O365 (just replace the string literals with your own details):

string username = "YOUR_USERNAME";
string password = "YOUR_PASSWORD";
string siteUrl = "https://XXX.sharepoint.com";

ClientContext context = new ClientContext(siteUrl);

SecureString pass = new SecureString();
foreach (char c in password.ToCharArray()) pass.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials(username, pass);

Site site = context.Site;
context.Load(site);
context.ExecuteQuery();

Web web = site.OpenWeb("YOUR_SUBSITE"); 
context.Load(web);
context.ExecuteQuery();

List docLib = web.Lists.GetByTitle("YOUR_LIBRARY");
context.Load(docLib);

FileCreationInformation newFile = new FileCreationInformation();
string filePath = @"YOUR_LOCAL_FILE";

newFile.Content = System.IO.File.ReadAllBytes(filePath);
newFile.Url = System.IO.Path.GetFileName(filePath);

Microsoft.SharePoint.Client.File uploadFile = docLib.RootFolder.Files.Add(newFile);
context.Load(uploadFile);
context.ExecuteQuery();

You can run it in console application. Two dll's that you need to reference are:

  • Microsoft.SharePoint.Client.dll
  • Microsoft.SharePoint.Client.Runtime.dll

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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