xamarin - "Unauthorized"Simple.OData.Client 通过使用来自 Xamarin PCL 的有效凭据访问 SharePoint REST API 的异常

标签 xamarin sharepoint-api simple.odata

在我们的 Xamarin 项目中使用 Simple.OData.Client 之前,我在 LINQPad 的帮助下进行了尝试。它的易用性给我留下了深刻的印象。当我将它构建到我们的 Xamarin 项目中时,我尝试从 SharePoint 的 REST Api 获取数据时遇到异常。

Simple.OData.Client.WebRequestException: Unexpected WebException encountered ---> System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decr...{Simple.OData.Client.WebRequestException: Unexpected WebException encountered ---> System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a

据我所知,此异常是由于我们的 SharePoint 实例使用自签名证书这一事实引起的。我尝试通过向 ServerCertificateValidationCallback

始终返回 true 来消除它
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

现在我总是从 Simple.OData.Client 得到未授权异常

Simple.OData.Client.WebRequestException: Unauthorized

初始调用来自 MainViewModel 通过业务层

    private async void InitializeAsync()
    {
        // TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:09:55]: Show loading indicator
        TaskEntity getTaskForCurrentMonthAsyncTask = await _taksBusinessLayer.GetTaskForCurrentMonthAsync();
        _timeToDisplay = getTaskForCurrentMonthAsyncTask.DueDate - DateTime.Now;
        // TODO [Anton Kalcik - Dienstag, 05. Mai 2015 17:10:04]: Hide loading indicator

        StartCountdownTimer();
    }

执行调用的类是 SharePointTaskRepository

public class SharePointTaskRepository : ITaskRepository
{
    private readonly string _collectionName;
    private readonly ODataClient _oDataClient;

    public SharePointTaskRepository(Uri sharepointUri, string collectionName, ICredentials credentials)
    {
        if (sharepointUri == null)
        {
            throw new ArgumentNullException("sharepointUri");
        }
        if (String.IsNullOrWhiteSpace(collectionName))
        {
            throw new ArgumentException("Argument can't be null, empty or white space!", "collectionName");
        }
        if (credentials == null)
        {
            throw new ArgumentNullException("credentials");
        }

        _collectionName = collectionName;

        var oDataClientSettings = new ODataClientSettings(sharepointUri, credentials);
        _oDataClient = new ODataClient(oDataClientSettings);
    }

    public async Task<IEnumerable<TaskModel>> ReadAsync(Expression<Func<TaskModel, bool>> filter, Expression<Func<TaskModel, object>> orderBy, int numberOfResults)
    {
        return await _oDataClient
                    .For<TaskModel>(_collectionName)
                    .Filter(filter)
                    .OrderBy(orderBy)
                    .Top(numberOfResults)
                    .FindEntriesAsync();
    }
}

我仔细检查了凭据,这绝对是正确的。使用 ServerCertificateValidationCallback 的代码在 ApplicationRuntimeSettings 中。此类是平台特定的、单例的,并通过依赖注入(inject)作为所有其他对象提供。

[assembly: Dependency(typeof(ApplicationRuntimeSettings))]
namespace AZeitReminder.Droid.Infrastructure
{
    public class ApplicationRuntimeSettings : ApplicationRuntimeSettingsBase
    {
        public ApplicationRuntimeSettings()
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
        }

        public override SQLiteConnection CreateSqLiteConnection()
        {
                string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                var path = Path.Combine(documentsPath, DatabaseFileName);
                var currentPlatform = new SQLitePlatformAndroid();
                var connection = new SQLiteConnection(currentPlatform, path);

                return connection;
        }

        public override CultureInfo GetCultureInfo()
        {
            var androidLocale = Java.Util.Locale.Default;
            var netLanguage = androidLocale.ToString().Replace("_", "-"); // NOTE [Anton Kalcik - Dienstag, 05. Mai 2015 17:21:10]: turns pt_BR into pt-BR
            return new CultureInfo(netLanguage);
        }
    }
}

最佳答案

你可以尝试设置PreAuthenticate = false;为您的要求。 Simple.ODataClient 在内部使用 HttpClientHandler。这个 HttpClientHandler 设置 PreAuthenticate = true;但您可以在 OnApplyClientHandler 中修改此处理程序并将该属性设置为 false。在您的代码中试试这个:

oDataClientSettings.OnApplyClientHandler = handler => handler.PreAuthenticate = false;

原因是您的 Sharepoint 服务器可以抛出“未经授权”作为质询响应,并且 WebRequest 不会回答质询,除非此属性为 false。

关于xamarin - "Unauthorized"Simple.OData.Client 通过使用来自 Xamarin PCL 的有效凭据访问 SharePoint REST API 的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30057151/

相关文章:

odata - simple.odata.client 查询参数

c# - Xamarin IF 语句匹配图像按钮及其背景

c# - .NET 2.0 WebService 在 Xamarin.Forms 默认可移植解决方案中不可用

c# - 使用rest api更新sharepoint中的多项选择字段

active-directory - 共享 API : Can't authenticate 'Sites.FullControl.All' in client_credential flow

sharepoint - 获取非用户应用程序的 SharePoint 特定访问 token

c# - EF 核心 : Foreign key returns null value

c# - 如何在 Xamarin iOS SQLite 中添加 SQLiteOpenFlags.FullMutex 标志

xamarin - 简单的 odata FindEntriesAsync 方法不返回集合

c# - 查询具有可为空 datetimetimeoffset 属性的链接实体时出现问题