我有一个 ASP.NET Web API 项目,在初始用户登录时,用户名和密码通过 SSL 在 http 标头中发送并由服务器验证。
服务器使用 UserId、randmon 64 字符串 (UserToken)、到期日期和客户端 IP 地址创建数据库记录。
然后将 UserToken 发送回客户端,然后存储在 cookie 中。
所有后续请求都在 http 标头中发送 UserToken,并由服务器使用调用 IP 地址进行验证。
这样,用户名和密码只发送一次,所有使用 UserToken 的调用都会被记录下来。
我创建了两个自定义 DelegatingHandler——LoginAuthenticationHandler 和 TokenAuthenticationHandler——它们处理 http 标头并发送适当的 200 或 400 http 响应。
///////////////
似乎我唯一的问题是我希望 LoginAuthenticationHandler 也将 UserToken 返回给客户端,因此它可以存储 cookie。
抱歉冗长:-\
另外-我是Web API的新手-所以也许这不是最好的地方-但是如果可以以这种方式将UserToken传递回LoginController,那将非常方便。
感谢您的任何输入:-)
一些相关的SO帖子:
是否可以将数据从 DelegatingHandler 传递到 ASP.NET Web API 中的控制器?
///////////////
public class LoginAuthenticationHandler : DelegatingHandler
{
public const string BasicScheme = "Basic";
public const string ChallengeAuthenticationHeaderName = "WWW-Authenticate";
public const char AuthorizationHeaderSeparator = ':';
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Get Authorization Http Header
var authHeader = request.Headers.Authorization;
if (authHeader == null)
{
// Unauthorized
return CreateUnauthorizedResponse();
}
// Check if Basic Authentication
if (authHeader.Scheme != BasicScheme)
{
// Unauthorized
return CreateUnauthorizedResponse();
}
// Decode UserName + Password from Http Header
var encodedCredentials = authHeader.Parameter;
var credentialBytes = Convert.FromBase64String(encodedCredentials);
var credentials = Encoding.ASCII.GetString(credentialBytes);
var credentialParts = credentials.Split(AuthorizationHeaderSeparator);
if (credentialParts.Length != 2)
{
// Unauthorized
return CreateUnauthorizedResponse();
}
var username = credentialParts[0].Trim();
var password = credentialParts[1].Trim();
// Authenticate Username + Password and Return UserToken
var userId = new Users().GetUserIdFromUserNamePassword(username, password);
if (userId == 0)
{
// Unauthorized
return CreateUnauthorizedResponse();
}
// User is Authorized - Create New UserToken
var ipAddress = HttpContext.Current.Request.UserHostAddress;
var userToken = new Users().CreateUserToken(ipAddress, userId);
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
//======================================================
// Return UserToken to Login Controller to be Stored as Cookie on the Client
// response.Content = userToken ??
// maybe set header for userToken ??
// HttpRequestMessage Properties ??
return response;
//======================================================
});
}
private static Task<HttpResponseMessage> CreateUnauthorizedResponse()
{
// Send Back Http Unauthorized if Authentication Fails
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.Headers.Add(ChallengeAuthenticationHeaderName, BasicScheme);
var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>();
taskCompletionSource.SetResult(response);
return taskCompletionSource.Task;
}
}
}