пароль не может содержать британский фунт в WCF? - PullRequest
12 голосов
/ 18 августа 2011

Обнаружил ли я ошибку в .NET Framework или я что-то не так делаю?

Вот история.

Вчера я пытался установить пароль на канале WCF следующим образом:

channelFactory.Credentials.UserName.UserName = credentials.Username;
channelFactory.Credentials.UserName.Password = credentials.Password;

, а затем вызвать метод веб-службы, когда я получил эту ошибку:

System.ServiceModel.CommunicationException
   Message=An error (The request was aborted: The request was canceled.) occurred while transmitting data over the HTTP channel.
   Source=mscorlib
   StackTrace:
     Server stack trace: 
        at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
        at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
        at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
        at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
        at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
        at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
        at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
        at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
     Exception rethrown at [0]: 
        at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
        at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
        at PocketKings.Tools.Services.PopulationManager.Client.PopulationService.IPopulationService.ResolvePopulationMember(ResolveRealmMemberQuery request)
   InnerException: System.Net.WebException
        Message=The request was aborted: The request was canceled.
        Source=System
        StackTrace:
             at System.Net.HttpWebRequest.GetResponse()
             at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
        InnerException: System.NotSupportedException
             Message=This method is not supported by this class.
             Source=System
             StackTrace:
                  at System.Net.BasicClient.EncodingRightGetBytes(String rawString)
                  at System.Net.BasicClient.Lookup(HttpWebRequest httpWebRequest, ICredentials credentials)
                  at System.Net.BasicClient.Authenticate(String challenge, WebRequest webRequest, ICredentials credentials)
                  at System.Net.AuthenticationManager.Authenticate(String challenge, WebRequest request, ICredentials credentials)
                  at System.Net.AuthenticationState.AttemptAuthenticate(HttpWebRequest httpWebRequest, ICredentials authInfo)
                  at System.Net.HttpWebRequest.CheckResubmitForAuth()
                  at System.Net.HttpWebRequest.CheckResubmit(Exception& e)
                  at System.Net.HttpWebRequest.DoSubmitRequestProcessing(Exception& exception)
                  at System.Net.HttpWebRequest.ProcessResponse()
                  at System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData)

Итак, я начал смотреть на это, и журналы показывают, что я даже не дошел до сервера. Оказывается, что метод платформы .NET, который генерирует исключение (System.Net.BasicClient.EncodingRightGetBytes (String rawString)), не любит знак британского фунта (£).

Я скопировал метод с отражателя и написал быстрый юнит-тест, и фунт - единственный символ, который ему не нравится из всех, которые я мог набрать на клавиатуре:

    internal static byte[] EncodingRightGetBytes(string rawString)
    {
            byte[] bytes = Encoding.Default.GetBytes(rawString);
            string strB = Encoding.Default.GetString(bytes);

            if (string.Compare(rawString, strB, StringComparison.Ordinal) != 0)
        {
            throw ExceptionHelper.MethodNotSupportedException;
        }
        return bytes;
}

Это мой модульный тест для проверки этого метода:

[Test]
public void test123()
{
       string domain = "localhost";
       string userName = "lukk";

       string charactersToCheck = @"¬`!£$%^&*()_+={}[]:;@'~#<>,.?/|\";

       foreach (var character in charactersToCheck.ToCharArray())
       {
              string internalGetPassword = character.ToString();

              try
              {
                     // begin - this assignement was copied from System.Net.BasicClient.Lookup method
                     byte[] inArray = EncodingRightGetBytes(
                           (!string.IsNullOrEmpty(domain) ? (domain + @"\") : "")
                           + userName
                           + ":"
                           + internalGetPassword);
                     //end
              }
              catch (Exception ex)
              {
                     Console.WriteLine(string.Format("this character is bad: {0}", internalGetPassword));
              }
       }
}

Как видите, EncodingRightGetBytes сравнивает две строки, и они отличаются, если исходная строка (rawString) содержит британский фунт.

EncodingRightGetBytes отлично работает, когда я заменяю «Encoding.Default.» На «Encoding.UTF8».…

Поиск в имени этого метода возвращает очень мало ссылок, одна из которых такова: http://support.microsoft.com/kb/943511

Я использую VS 2010 с проектом asp.net, настроенным на использование .net 3.5.

Так это будет ошибка в .NET Framework или я что-то не так делаю?

Edit: Когда во время выполнения теста я запрашиваю Encoding.Default в окне Immediate, я получаю следующее:

?Encoding.Default
    {System.Text.SBCSCodePageEncoding}
    [System.Text.SBCSCodePageEncoding]: {System.Text.SBCSCodePageEncoding}
    BodyName: "iso-8859-2"
    CodePage: 1250
    dataItem: {System.Globalization.CodePageDataItem}
    decoderFallback: {System.Text.InternalDecoderBestFitFallback}
    DecoderFallback: {System.Text.InternalDecoderBestFitFallback}
    EncoderFallback: {System.Text.InternalEncoderBestFitFallback}
    encoderFallback: {System.Text.InternalEncoderBestFitFallback}
    EncodingName: "Central European (Windows)"
    HeaderName: "windows-1250"
    IsBrowserDisplay: true
    IsBrowserSave: true
    IsMailNewsDisplay: true
    IsMailNewsSave: true
    IsReadOnly: true
    IsSingleByte: true
    m_codePage: 1250
    m_deserializedFromEverett: false
    m_isReadOnly: true
    WebName: "windows-1250"
    WindowsCodePage: 1250

1 Ответ

2 голосов
/ 21 августа 2011

Я столкнулся с чем-то похожим с asp, мне удалось обойти проблему с помощью следующей конфигурации.

<system.web>    
<globalization
 fileEncoding="utf-8"
 requestEncoding="utf-8"      
 responseEncoding="utf-8"
 culture="en-GB"
 uiCulture="en-GB"/>
...

Насколько мне известно, тег глобализации работает одинаково для WCF, когда вы устанавливаете

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

Обновление: только что отмечено MSDN внизу страницы указано следующее:

Язык конфигурации ASP.NET позволяет указывать культуру для индивидуальных услуг. WCF не поддерживает эту конфигурацию настройка за исключением режима совместимости ASP.NET. Локализовать WCF Служба, которая не использует режим совместимости ASP.NET, скомпилируйте тип сервиса в специфичные для культуры сборки и Конкретные культурные конечные точки для каждой специфической для культуры сборки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...