2011-08-18 8 views
12

Czy wykryłem błąd w strukturze .NET lub czy robię coś nie tak?hasło nie może zawierać funta brytyjskiego w WCF?

Oto historia.

starałem się ustawić hasło na kanale WCF wczoraj tak:

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

a następnie wywołać metody usługi sieci Web, kiedy mam ten błąd:

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) 

Więc zacząłem szukać na nim i dzienniki pokazują, że nie dostaję się nawet do serwera. Okazuje się, że metoda ramowa .NET, która zgłasza wyjątek (System.Net.BasicClient.EncodingRightGetBytes (String rawString)) nie lubi brytyjskiego znaku funta (£).

skopiowane metodę z odbłyśnikiem i pisał test szybki jednostkową i funt jest jedyną postacią, która nie robi jak z wszystkim mogę wpisać na klawiaturze:

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; 
} 

To jest mój testów jednostkowych w celu sprawdzenia ta metoda:

[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)); 
       } 
     } 
} 

Jak widać EncodingRightGetBytes porównuje dwa ciągi i są one różne, jeśli oryginalny łańcuch (rawString) zawiera funta brytyjskiego.

EncodingRightGetBytes działa dobrze, kiedy należy wymienić z ...

Googling nazwa ta metoda przynosi z powrotem bardzo kilka linków, jednym z nich jest to „Encoding.Default.” „Encoding.UTF8.”: http://support.microsoft.com/kb/943511

Używam VS 2010 z zestawem projektów asp.net do używania .net 3.5.

Czyli to byłby błąd w strukturze .NET lub czy robię coś nie tak?

Edit: Kiedy kwerendy Encoding.Default w okienku bezpośrednim podczas jazdy mój test uzyskać to:

?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

Zakładając, że używasz brytyjskiej klawiatury, co się stanie, jeśli wpiszesz ±, § lub € jako część ciągu (wszystkie zostaną znalezione na klawiaturze w Wielkiej Brytanii)? Jeśli te również się nie powiodą, to problem jest zdecydowanie z kodowaniem 7 lub 8 bitowym, ponieważ wszystkie te znaki mają kody powyżej 128 (tj. Używają 8 bitów) i dlatego nie mogą być przetwarzane poprawnie z domyślnym kodowaniem, które, najprawdopodobniej , jest Latin1 lub jego pewną odmianę. Czy istnieje sposób na zmianę kodowania na UTF8? –

+0

To brzmi jak problem z zakodowanym znakiem funta jako "rozszerzonym" znakiem ASCII, który może mieć sens jedynie, jeśli znasz stronę kodową, która była używana (oczywiście hash hasła nie zawiera strony kodowej używanej do make it), więc metoda kodowania może słusznie odrzucić niejednoznacznie zakodowane znaki. UTF8 brzmi jak właściwe rozwiązanie. – David

+0

Witajcie, dziękuję za komentarze. @Aleks - Dodałem te trzy znaki: "± § €" do mojego ciągu testowego i wszystkie zdały test. BTW moja klawiatura to angielski (Irlandia) – lukk

Odpowiedz

2

doświadczyłem czegoś podobnego z ASP, udało mi się obejść problem przy użyciu następująca konfiguracja.

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

Do mojej wiedzy tag globalizacja działa tak samo dla WCF po ustawieniu

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 

UPDATE: Właśnie sprawdzone MSDN na dole strony stwierdza, co następuje:

The ASP.NET configuration language allows you to specify the culture for individual services. The WCF does not support that configuration setting except in ASP.NET compatibility mode. To localize a WCF service that does not use ASP.NET compatibility mode, compile the service type into culture-specific assemblies, and have separate culture-specific endpoints for each culture-specific assembly.

Powiązane problemy