ASP.net Web API RESTful Web 服务 + 基本身份验证

Posted

技术标签:

【中文标题】ASP.net Web API RESTful Web 服务 + 基本身份验证【英文标题】:ASP.net Web API RESTful web service + Basic authentication 【发布时间】:2013-06-11 21:33:44 【问题描述】:

我正在使用 ASP.Net Web Api 实现一个 RESTful Web 服务。我已经得出结论使用基本身份验证 + SSL 来进行身份验证部分。实现它的最佳/正确方法是什么?

我的第一次尝试是手动进行,解析授权标头,根据我的数据库解码和验证用户。它有效,但我想知道我是否遗漏了什么。

我见过一些使用用户角色和主体的解决方案。虽然我不确定这些实际上是做什么的,但我几乎可以肯定我不需要这些,因为在我的数据库中我定义了我自己的用户和他们的角色。

我还没有完全理解的是,服务的消费者是否必须在每个请求中发送凭据,或者它们是否被缓存。我的服务应该做些什么来实现这一点,还是完全由消费者来处理?

最后一个关于客户端使用 javascript 发出请求的问题。如果他们尝试使用该服务,是否会出现任何“跨域请求”问题?

【问题讨论】:

【参考方案1】:

Jamie Kurtze 在这里ASP.NET Web API REST Security Basics 提供了使用基本身份验证的一个很好的解释

据我了解,如果您希望您的请求是无状态的,那么每个请求都需要设置 Authentication 字段

Jamie Kurtze 将必要的代码封装在派生自 DelegateHandler 的类中,而 Rick Strahl 使用过滤器检查调用是否有效。您可以在A WebAPI Basic Authentication Authorization FilterA WebAPI Basic Authentication Authorization Filter 上阅读他关于此主题的博客文章

【讨论】:

您好,当我写下这个问题时,我并不清楚如何使用 Principals 和 Roles(以及它们与我自己的用户有什么关系)。我现在所做的是使用 Authentication 标头来传递凭据和 Http 模块来统一检查它们。有时间我会看看你的链接。 我的实现现在工作得很好,但这些对于未来的读者来说是很好的链接。 您的第一个链接 ASP.NET Web Api REST 安全基础知识已失效【参考方案2】:

通过将[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 密钥来实现。

【讨论】:

我已经解决了这个问题,但感谢您的回答。我发现在所有 API 调用中,在 Authorization 标头中传递用户名和密码更容易,而不是使用您建议的令牌方法。 @Edward 非常感谢您的帖子,我觉得它最有帮助。您在此示例中使用什么用户和角色机制?因为我看到你创建了一个新的 GenericPrinsiple。您能否详细说明我如何将您的解决方案集成到一个新的空 web api 项目中。 @Zapnologica 此代码使用 Microsoft 在 VS2013 之前使用的旧会员身份模型。带有 VS2013 的模板使用新的基于 OWIN 的身份系统,该系统执行自定义用户名/密码身份验证,然后使用不记名令牌,从而无需 BasicHttpAuthorize。 @EdwardBrey,好吧。哈哈这让我有点失望,所以你能指出我正确的方向吗?我需要上面的示例,但需要使用 owin 变体。 @Zapnologica 对不起,但我不知道手,因为我不需要 OWIN 的这种方法。快速搜索显示an article,其中提到Request.GetOwinContext 以获取可以调用Authentication.User 的上下文。或许答案就在那个方向。【参考方案3】:

在这里查看一个好的基本身份验证实现

http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/

有更多关于它的阅读: https://github.com/thinktecture/Thinktecture.IdentityModel.45/wiki

【讨论】:

这些链接并不能真正回答我的问题。可能只有第一个问题,但它们指的是配置第三方安全库。由于时间不够,我想避免使用更多的库。

以上是关于ASP.net Web API RESTful Web 服务 + 基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何将 .aspx 页面中的 ASP.NET Web 方法转换为 RESTful API?

使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API

ASP.NET Web API 简介

ASP.NET Core Web API

WCF 与 ASP.NET Web API [关闭]

ASP.NET Web API 从 MVC 4 控制器失败