【问题标题】:WCF DataServices Service Operation Parameter - Character ReplacementWCF DataServices 服务操作参数 - 字符替换
【发布时间】:2012-07-13 19:24:58
【问题描述】:

我有一个很奇怪的问题(使用 SL5,WCF DataServices 5.0.1): 我有一个带有 2 个字符串参数(用户名、密码)的 ServiceOperation,用于检查用户是否存在

public IQueryable<User> Login(string username, string password)
{...}

当我尝试调用它时,一切正常,除了密码哈希中包含“+”字符的情况。在这种情况下,它似乎被替换为空白字符:

var pwd = CRQWKrKzCcQVnlhk2zl0j5QM+c5ujQGMv0XXnh4genI=
this.Context.BeginExecute<User>(new Uri(string.Format("/Login?username='{0}'&password='{1}'", username, pwd), UriKind.Relative), (ar) => { .. }, null);

如果我用 Fiddler 抓取它,Request-Header 对我来说似乎没问题...

GET /Service.svc/Login?username='xyz'&password='CRQWKrKzCcQVnlhk2zl0j5QM+c5ujQGMv0XXnh4genI=' HTTP/1.1

但在 WebForms-Tab 中,Password-QueryString 已经有一个空格而不是“+”。如果我在服务器上调试,结果相同...

你们中有人知道为什么要替换“+”吗? 是否还有其他无效字符? 我怎样才能避免这种情况?

更新/编辑:

令人惊讶的是,以下查询按预期工作:

var query = (DataServiceQuery<User>) from c in this.Context.Users
                                             where
                                                 c.Username.Equals(username.ToLower()) &&
                                                 c.Password.Equals(Cryptography.ComputeSha256Hash(password + username.ToLower())) 
                                             select c;

提前致谢!

【问题讨论】:

  • 您是否尝试过在执行 URL 之前对其进行编码?我相信 + 和 = 都可以编码,而且我不认为对 Execute 的调用有任何自动尝试编码的逻辑。
  • 我认为 .NET 中的字符串总是 Unicode (UTF16)?尽管如此,我还是尝试了一个像“Test+123”这样的修复密码,这导致了同样的谜团。但是我尝试了以下令人惊讶的工作(请参阅我的问题中的更新部分)!

标签: wcf-data-services silverlight-5.0 service-operations


【解决方案1】:

URL 的查询字符串部分需要正确编码。对 WCF DS 客户端 LINQ 提供程序(例如,context.Users.Where(...))的调用由客户端堆栈自动编码。对context.Execute 的调用不会以这种方式修改 URL,因此那里的值需要通过其他代码进行编码。

在 Visual Studio 中试试这个,看看有什么不同:

using System;
using System.Data.Services.Client;
using System.Linq;

namespace Scratch
{
    public class Program
    {
        public static void Main()
        {
            var context = new DataServiceContext(new Uri("http://services.odata.org/OData/OData.svc/"));
            var query1 = context.CreateQuery<Category>("Categories").Where(c => c.Name == "abcd+efgh=ijlk");
            var query2 = context.Execute<Category>(new Uri("http://services.odata.org/OData/OData.svc/Categories()?$filter=Name eq 'abcd+efgh=ijlk'"));
            Console.WriteLine("context.Categories.Where(...): {0}", query1.ToString());
            Console.WriteLine("context.Execute<Category>(...): {0}", ((QueryOperationResponse)query2).Query.ToString());
        }
    }

    public class Category
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

【讨论】:

    【解决方案2】:

    感谢马克斯塔福德的提示。 我现在已经解决了这个问题:

    var pwd = Uri.EscapeDataString(Cryptography.ComputeSha256Hash(password + username.ToLower()));
    

    查询现在看起来像这样:

    /GET Service.svc/Login?username='xyz'&password='CRQWKrKzCcQVnlhk2zl0j5QM%252Bc5ujQGMv0XXnh4genI%253D'
    

    并且在服务器上等效的 unsecaping:

    var pwd = Uri.UnescapeDataString(password);
    

    http://www.codebadger.com/blog/post/2010/08/10/Use-EscapeUriString-instead-of-UrlEncode-for-Silverlight.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多