我正在使用ASP.Net Web Api实现RESTful Web服务。我已经得出结论,使用基本身份验证+ SSL来执行身份验证部分。实现它的最佳/正确方法是什么?
我的第一次尝试是手动执行,解析Authorization标头,根据我的数据库解码和验证用户。它有效,但我想知道我是否遗漏了一些东西。
我见过一些使用用户角色和主体的解决方案。虽然我不确定这些实际上做了什么,但我几乎肯定我不会需要这些,因为在我的数据库中我定义了自己的用户和他们的角色。
我还没有完全理解的是,服务的消费者是否必须在每个请求中发送凭据,或者以某种方式缓存它们。我的服务是否应该为了实现这一点而做某事,或者完全取决于消费者来处理这个问题?
关于客户端使用javascript发出请求的最后一个问题。如果他们试图使用该服务会有任何“跨域请求”问题吗?
答案 0 :(得分:30)
Jamie Kurtze在此ASP.NET Web API REST Security Basics
提供了使用基本身份验证的详细说明根据我的理解,如果您希望您的请求是无状态的,那么每个请求都需要设置身份验证字段
Jamie Kurtze将必要的代码包装在派生自DelegateHandler的类中,而Rick Strahl使用Filter检查调用是否有效。您可以在A WebAPI Basic Authentication Authorization Filter
上关于此主题的博客文章中阅读更多内容答案 1 :(得分:24)
通过向适当的控制器/方法添加[BasicHttpAuthorize]
属性,对初始(登录)请求使用基本身份验证。如果需要,请使用属性指定Users和Roles。将BasicHttpAuthorizeAttribute
定义为专门的AuthorizeAttribute,如下所示:
public class BasicHttpAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (Thread.CurrentPrincipal.Identity.Name.Length == 0) { // If an identity has not already been established by other means:
AuthenticationHeaderValue auth = actionContext.Request.Headers.Authorization;
if (string.Compare(auth.Scheme, "Basic", StringComparison.OrdinalIgnoreCase) == 0) {
string credentials = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(auth.Parameter));
int separatorIndex = credentials.IndexOf(':');
if (separatorIndex >= 0) {
string userName = credentials.Substring(0, separatorIndex);
string password = credentials.Substring(separatorIndex + 1);
if (Membership.ValidateUser(userName, password))
Thread.CurrentPrincipal = actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity(userName, "Basic"), System.Web.Security.Roles.Provider.GetRolesForUser(userName));
}
}
}
return base.IsAuthorized(actionContext);
}
}
初始响应包含用户的API密钥。使用API密钥进行后续调用。这样,即使用户更改用户名或密码,客户端的身份验证仍然有效。但是,在更改密码时,请为用户提供“断开客户端”选项,您可以通过删除服务器上的API密钥来实现。
答案 2 :(得分:1)