我有一个 Web API 2 项目,我们正在使用基本授权。客户端在授权标头中发送用户名:密码 - 我们将其提取并连接到 LDAP 服务器以
- 验证用户
- 验证他们的密码,然后
- 从他们的 LDAP 响应中获取一个属性值并将其传递给请求的 IPrincipal。
问题是,当我通过System.Web.Http.ApiController.User.Identity.Name访问控制器中的IPrincipal时,我看到传入的值并不总是正确的!
示例:在消息处理程序或过滤器中,我将 IPrincipal 设置为:
public class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter
{
...other code...
private IPrincipal ReturnPrincipal(string UserID, List<string> roles)
{
roles.Add("SomeRole");
// UserID = 7144 or 8899 (load testing)
var identity = new GenericIdentity(UserID, "Basic");
var principal = new GenericPrincipal(identity, roles.ToArray());
return principal;
}
}
编辑:这是我们在过滤器中设置主体的方式:
var principal = await AuthenticateAsync(UserID, password, cancellationToken);
if (principal == null)
{
// Authentication was attempted but failed. Set ErrorResult to indicate an error.
context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
}
else
{
// Authentication was attempted and succeeded. Set Principal to the authenticated user.
context.Principal = principal;
}
在请求的生命周期后期,在控制器中,我尝试像这样访问这个值:
protected bool IsAuthorized(string UserID)
{
return User.Identity.Name == UserID;
}
所以这里发生的是我从ApiController.User.Identity.Name获取User.Identity.Name,在负载测试下,我同时发送 2 个线程并行请求 - 当我这样做时,请求对象显示正确URL 中的 ID,但是,过滤器中设置的 IPrincipal 不正确。这是一个具有预期结果的固定测试,所以这永远不会发生。如果它错开电话,问题就不会出现!如果同时发送呼叫,则问题的发生率为 100%。
这是我调用服务的方式:
var task1 = Task.Run(() => CallServerInParallel(requests2, api));
var task2 = Task.Run(() => CallServerInParallel2(requests2, api));
Task.WaitAll(task1, task2);
...
private static void CallServerInParallel2(List<int> requests2, string api)
{
Parallel.ForEach(requests2, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, async p =>
{
var client = new RemoteClient(api);
client.AddAuthHeader("d2JsMTE4NTgzOUBbdGVhY2NlcHQuY29tOnRlc3QxMjM0");
var response = await client.Get<dynamic>("CustomerSite/5537");
});
}
private static void CallServerInParallel2(List<int> requests2, string api)
{
Parallel.ForEach(requests2, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, async p =>
{
var client = new RemoteClient(api);
client.AddAuthHeader("d2JsMTE4NTgzOUBkdGVhY1NlcHQuY29tOnRlc3QxMjM0");
var response = await client.Get<dynamic>("CustomerSite/5538");
});
}
如何访问请求的正确 IPrincipal.User.Identity.Name?