【问题标题】:WCF 4.0 REST username password authenticationWCF 4.0 REST 用户名密码认证
【发布时间】:2011-11-19 21:02:00
【问题描述】:

我一直在努力使用 ASP.Net 成员/角色提供程序在 WCF 4.0 RESTfull 服务中进行用户名/密码身份验证/授权。

花了两天时间试图找到大多数人都同意的东西,我放弃了。很多混乱似乎是因为没有专门针对 WCF 4.0 的信息。

有人能好心吗

  1. 就开始使用 WCF 4.0 + REST 是否是一个好主意给出权威的看法?
  2. 概述执行此操作的普遍接受步骤(或链接)。
  3. 提供完成此操作所需的相当完整的代码示例。

编辑: 任何可以使用 VS 2010 中的 WCF 服务应用程序模板为 RESTfull WCF 4.0 服务提供用户名/密码身份验证和授权的完整示例(甚至只是指向完整示例的链接)的人的赏金。

【问题讨论】:

  • 所以 IIS NT 身份验证不是一个可行的选择?
  • 您可以通过 ASP.net Web 应用程序项目公开 WCF 合同,并可能在您的 web.config 中应用 ASP.net 身份验证。
  • 不需要使用 SOAP 标头吗?使用 Membership 和 Roleproviders 并不是真正的问题。它将所有东西连接在一起。
  • 启动一个空的 ASP.net Web 应用程序,添加一个 svc 并将您的 web.config 更改为套件。你可能会感到惊喜。即stackoverflow.com/questions/4949792/…
  • 对不起,我不明白。首先将如何对其进行身份验证?那会是 Restfull 吗?

标签: wcf wcf-security restful-authentication wcf-rest


【解决方案1】:

我认为您的问题的答案取决于您的服务的目的以及将要使用它的应用程序的类型。

如果您有一个现有的 ASP .Net 应用程序,并且希望将其部分功能公开为 RESTfull 服务,您将能够使用 AJAX 使用客户端,那么 WCF 可能不是最佳选择。在这种特殊情况下,您已经在 Web 应用程序中拥有了一个身份验证用户,并且您希望在 AJAX 调用期间传播该身份验证。实现这一点实际上非常简单。

ASP .Net Forms 身份验证基于成功登录后生成并传递给浏览器的身份验证cookie。浏览器对与您的应用程序位于同一域中的任何 URL 的每次调用也将包含身份验证 cookie。在 ASP .Net MVC 中,您可以简单地将服务方法实现为需要授权的控制器操作,一切都会在幕后为您完成。

在经典的 ASP .Net 中,您可以使用 PageMethods 来实现您的服务方法,并且会再次为您发送和验证 cookie(PageMethods herehere 的示例)。

另一方面,如果您的服务将在浏览器之外使用(例如从桌面或移动应用程序),那么 WCF 可能确实是实现该服务的正确工具。但是,ASP .Net 表单身份验证并不是实现安全性的最佳选择。 REST 服务的主要目的是简单,以便客户端可以轻松地在每个平台上实现,并且 ASP .Net 表单身份验证的基于 cookie 的机制并不是最直接的。

OAuth 是一种专门为 Web 服务上下文中的用户身份验证而构建的协议。它的第二个版本仍在草稿中(查找规范here),但很可能这是您想要使用的版本,因为它比 OAuth 1.0 简单得多。 Facebook 已经通过 OAuth 2.0 实现了其 API 身份验证(详情 here),您可能想查看他们的实现以获取灵感。

除了用户身份验证之外,OAuth 还确保使用应用程序(服务客户端)身份验证,并确保用户永远不会直接在客户端应用程序中输入其凭据。如果这超出了您的实际需要,您可以创建一个受 OAuth 2.0 启发的自定义实现。

首先,您需要通过 HTTPS 公开您的服务,以便对服务和客户端之间的所有通信进行加密。其次,您需要在服务中创建一个登录方法,如下所示:

string Login(string user, string password);

成功登录后,上述方法将返回一个身份验证令牌。然后将在所有其他方法上使用和验证身份验证令牌。例如:

Employee[] GetAllEmployees(string authToken)
{
  // verify token here

  // return data if user authenticated by token
}

在上述架构中,authToken 与 ASP .Net 表单身份验证中的身份验证 cookie 具有相同的作用,但它是作为简单参数传递的。您将负责实现生成令牌的算法(它们必须足够长且唯一,使用像 here 这样的算法)并存储和验证它们。

【讨论】:

  • 如何在 GetAllEmployees 中访问令牌,因为它不维护状态.....传递给 GetAllEmployees 的 authToken 将用什么检查?
  • @Anil,authTokens 可以保存在不同的持久数据存储中,例如数据库。
  • 为什么不使用Headers而不是使用数据库来存储和管理服务层的状态......而且它使我们增加了定期销毁它的额外开销......客户端可以添加标题,我们可以在 application_AuthenticateRequest 事件中验证标头...标头可以包含加密的用户名和密码或令牌之类的任何内容
  • @Anil,标头是在客户端和服务器之间传递数据的一种方式,而不是一种存储方式。您可以使用标头传递令牌,但是您仍然需要在服务器端验证它们,这意味着当它们处于活动状态时,它们需要保存在数据存储中。数据库只是一个选项,你可以选择更适合你的。传递加密的用户 + 密码是一个不好的选择,因为:a)它相当于一个无限的登录会话(无法控制到期,除非更改密码),b)你不应该存储密码
  • 在这种情况下,我们需要在您在服务层提到的登录方法中传递用户名/密码......这又是一个安全威胁......(即使它是加密的) ....正如您提到的,首先调用服务的登录方法,然后发出令牌,然后使用传递给它的令牌调用休息方法....我所说的方法不需要存储在持久数据存储中。 ....在服务器端,您可以将其保存在配置密钥中(再次加密)并从配置设置中进行比较...而且我说过您可以传递用户名/密码或加密令牌
【解决方案2】:

WCF Web Api 使编写 WCF Rest 服务变得非常容易,但它也有一些限制。对于身份验证,您需要使用WCF Rest Contrib

如果您想最大限度地控制您的服务设计,那么您应该求助于 ASP.NET MVC 并为每个服务方法编写控制器方法。

【讨论】:

    【解决方案3】:

    一种方法是使用安全密钥。和令牌

    1. 每个客户都有他在第一次请求时发送的安全密钥, 可能在标题中。
    2. 您可以生成key = MD5Hash(username+password);
    3. 作为响应,他得到 token ,然后在每个 要求。令牌可以是 Guid。每个令牌都在 x 分钟后过期。
    4. 在服务器端,您可以维护一个像 Dictionay 这样的单例字典,以便在当前时间 > 过期时间将其从字典中删除时检查令牌过期时间。
    5. 要更新会话,请将更新会话方法放入您的代码中。

    为了极高的安全性

    拥有私钥/公钥对,客户端将使用公钥加密整个帖子数据,您将使用私钥解密。

    【讨论】:

      【解决方案4】:

      这是一个使用 asp.net mvc 完成的示例

      当我打电话给http://localhost:57322/Test/SecureMethod/ 时,我得到一个错误。但是,如果我先调用http://localhost:57322/Test/Login?username=test&password=abc,那么原始 URL 会返回有效结果。

      namespace MvcApplication1.Controllers
      {
          public class TestController : Controller
          {
              public ActionResult Login(string username, string password)
              {
                  if (username=="test" && password == "abc")
                  {
                      FormsAuthentication.SetAuthCookie(username, true);
                      return Json(true, JsonRequestBehavior.AllowGet);
                  }
                  return Json(false, JsonRequestBehavior.AllowGet);
              }
      
              [Authorize]
              public ActionResult SecureMethod()
              {
                  return Json("Hello world",JsonRequestBehavior.AllowGet);
              }
      
          }
      }
      

      如果您已经编写了 .svc 并且它们不是通过 MVC 完成的,您可以将它们放在通过 web.config 保护的任何文件夹中,然后在进行任何安全调用之前使用上面的登录方法登录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-28
        • 1970-01-01
        • 1970-01-01
        • 2011-08-23
        相关资源
        最近更新 更多