当“ UseDefaultCredentials”设置为True时,出现“ 401未经授权”错误

时间:2019-04-02 00:54:26

标签: exchangewebservices ews-managed-api

当我在 WebCredentials 中的呼叫中指定用户名和密码时,对EWS的呼叫工作正常。如果将 ExchangeService.UseDefaultCredentials 属性设置为True,则会收到401未经授权错误。

我不知道这是否重要,但是我们的Exchange管理员告诉我我正在混合环境中工作。我们同时运行Exchange Online和Exchange 2010(我认为应该是2013)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange.WebServices.Data;
using System.Security.Cryptography.X509Certificates;
using System.Net; 

namespace EWSLib
{
    class Program
    {
        static ExchangeService _service;
        static void Main(string[] args)
        {
            string defaultEmail = System.DirectoryServices.AccountManagement.UserPrincipal.Current.EmailAddress;            
            ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;


            try
            {
                _service = new ExchangeService();

                Appointment meeting = new Appointment(_service);

                //-----------------------------------------------
                // If I comment out
                // "_service.UseDefaultCredentials = true" 
                // and uncomment the line "_service.Credentials = new WebCredentials("user@company.com", "password")"
                // Then Everything works fine.
                //------------------------------------------------
                _service.UseDefaultCredentials = true;
                //_service.Credentials = new WebCredentials("user@company.com", "password");


                _service.TraceEnabled = true;
                _service.TraceFlags = TraceFlags.All;
                //_service.AutodiscoverUrl(defaultEmail, RedirectionUrlValidationCallback);
                _service.Url = new Uri("https://example.com/EWS/Exchange.asmx");

                // TEST MEETING
                meeting.Subject = "The subject";
                meeting.Body = "The boddy";
                meeting.Start = DateTime.UtcNow.AddDays(5);
                meeting.End = DateTime.UtcNow.AddDays(5).AddHours(1);
                meeting.Location = "Someplace";
                meeting.IsReminderSet = true;



                meeting.RequiredAttendees.Add(defaultEmail);
                meeting.ReminderMinutesBeforeStart = 60;


                // Delegation
                meeting.Save(new FolderId(WellKnownFolderName.Calendar, "delegator@company.com"), SendInvitationsMode.SendToAllAndSaveCopy);



                // Verify that the meeting was created.
                Item item = Item.Bind(_service, meeting.Id, new PropertySet(ItemSchema.Subject));




            }
            catch (Exception e)
            {
                //System.Diagnostics.Debug.WriteLine(e);
                Console.WriteLine(e);
            }

            Console.ReadLine();
        }

        private static bool RedirectionUrlValidationCallback(string redirectionUrl)
        {
            // The default for the validation callback is to reject the URL.
            bool result = false;
            Uri redirectionUri = new Uri(redirectionUrl);
            // Validate the contents of the redirection URL. In this simple validation
            // callback, the redirection URL is considered valid if it is using HTTPS
            // to encrypt the authentication credentials. 
            if (redirectionUri.Scheme == "https")
            {


                result = true;
            }
            return result;
        }

        private static bool CertificateValidationCallBack(
    object sender,
        System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    System.Security.Cryptography.X509Certificates.X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            // If the certificate is a valid, signed certificate, return true.
            if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
            {
                Console.WriteLine("Valid Signed Certificate");
                return true;
            }

            // If there are errors in the certificate chain, look at each error to determine the cause.
            if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
            {
                if (chain != null && chain.ChainStatus != null)
                {
                    foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
                    {
                        if ((certificate.Subject == certificate.Issuer) &&
                       (status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
                        {
                        // Self-signed certificates with an untrusted root are valid. 
                            Console.WriteLine("Self-signed certificates with an untrusted root are valid.");
                            continue;
                        }
                        else
                        {
                            if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
                            {
                                // If there are any other errors in the certificate chain, the certificate is invalid,
                                // so the method returns false.
                                Console.WriteLine("there are any other errors in the certificate chain");
                                return false;
                            }
                        }
                    }
                }

                // When processing reaches this line, the only errors in the certificate chain are 
                // untrusted root errors for self-signed certificates. These certificates are valid
                // for default Exchange server installations, so return true.
                Console.WriteLine("Valid for some reason");
                return true;
            }
            else
            {
                // In all other cases, return false.
                Console.WriteLine("there are any other errors in the certificate chain");
                return false;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

如果您的邮箱位于Office365上,那么我建议您改用Oauth。由于明年EWS https://blogs.technet.microsoft.com/exchange/2018/07/03/upcoming-changes-to-exchange-web-services-ews-api-for-office-365/的基本身份验证将不复存在。

如果您使用oAuth,则可以将Windows集成的Auth与ADAL库https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/AcquireTokenSilentAsync-using-Integrated-authentication-on-Windows-(Kerberos)结合使用,以利用当前登录的用户的优势。

答案 1 :(得分:0)

我们的用户帐户位于Exchange Online上。这就是为什么将 UseDefaultCredentials 设置为 True 无效的原因。

From Microsoft

  

如果用户的邮箱作为Office 365的一部分托管在Exchange Online或Exchange Online中,则不能使用已登录用户的默认凭据。相反,请使用Credentials属性设置用户的凭据。对于Exchange Online,用户的凭据必须采用用户主体名称(UPN)形式。