我有一个非常奇怪的问题(使用SL5,WCF DataServices 5.0.1): 我有一个ServiceOperation,带有2个字符串参数(用户名,密码),用于检查用户是否存在
public IQueryable<User> Login(string username, string password)
{...}
当我尝试调用此方法时,Everythings工作正常,但密码哈希中包含“+”字符的情况除外。在这种情况下,似乎它被替换为空白字符:
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;
提前致谢!
答案 0 :(得分: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; }
}
}
答案 1 :(得分:1)
感谢Mark Stafford的提示。 我现在已经解决了这个问题:
var pwd = Uri.EscapeDataString(Cryptography.ComputeSha256Hash(password + username.ToLower()));
查询现在看起来像这样:
/GET Service.svc/Login?username='xyz'&password='CRQWKrKzCcQVnlhk2zl0j5QM%252Bc5ujQGMv0XXnh4genI%253D'
在服务器上等效的取消行为:
var pwd = Uri.UnescapeDataString(password);