c# - 如何让 ServiceStack 身份验证工作? (使用 iPhone 客户端)

标签 c# web-services authentication servicestack basic-authentication

我们聘请了一个为我们编写 iPhone 应用程序的承包商,我开始使用 ServiceStack 为其编写后端服务。

总的来说,我在授权方面苦苦挣扎:使用什么样的授权以及如何实现它。
我不太了解 ServiceStack、HTTP 和授权(还)。我读过 this ,但我可能还是做错了什么。

我将使用现有遗留数据库中的用户名和密码进行身份验证(但仅此而已 - 不注册新用户,没有不同的权限。只是进行身份验证)。
所以我需要编写自己的提供程序。

this tutorial 的帮助下,我成功地实现了一个有效的 CredentialsAuthProvider .
当我在浏览器中测试它时它起作用了:

  • 调用我的服务并获得 401
  • POST 到 auth/credentials
  • 再次调用我的服务并获得正确的结果

但是,当我在 Fiddler 中尝试时,我注意到相同的工作流程不起作用。

auth/credentials 的 POST 有效。我发布这个:

POST http://localhost:52690/auth/credentials?format=json HTTP/1.1
User-Agent: Fiddler
Host: localhost:52690
Content-Length: 74
Content-Type: application/json; charset=utf-8

{
  "UserName": "chspe",
  "Password": "xyz",
  "RememberMe": true
}

...然后得到这个:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Fri, 14 Jun 2013 13:07:35 GMT
X-AspNet-Version: 4.0.30319
X-Powered-By: ServiceStack/3,949 Win32NT/.NET
Set-Cookie: ss-id=3YUUgfwIeJd7PedFK5Th; path=/; HttpOnly
Set-Cookie: ss-pid=zQJ5Z4Vq7AY+BpVwbttj; expires=Tue, 14-Jun-2033 13:07:35 GMT; path=/; HttpOnly
Set-Cookie: ss-opt=perm; expires=Tue, 14-Jun-2033 13:07:35 GMT; path=/; HttpOnly
Set-Cookie: X-UAId=; expires=Tue, 14-Jun-2033 13:07:35 GMT; path=/; HttpOnly
Cache-Control: private
Content-Type: application/json; charset=utf-8
Content-Length: 75
Connection: Close

{"sessionId":"zQJ5Z4Vq7AY+BpVwbttj","userName":"chspe","responseStatus":{}}

我觉得不错。
但是随后调用我的实际服务仍然返回 401:

GET http://localhost:52690/hello/world?format=json HTTP/1.1
User-Agent: Fiddler
Host: localhost:52690
Content-Length: 0
Content-Type: application/json; charset=utf-8

响应:

HTTP/1.1 401 Unauthorized
Server: ASP.NET Development Server/10.0.0.0
Date: Fri, 14 Jun 2013 13:07:44 GMT
X-AspNet-Version: 4.0.30319
WWW-Authenticate: credentials realm="/auth/credentials"
X-Powered-By: ServiceStack/3,949 Win32NT/.NET
Cache-Control: private
Content-Length: 0
Connection: Close

(这是来自 ServiceStack.Host.AspNet packageHelloService,我刚刚添加了 [Authorize] 属性)

实际请求是正确的,因为当我删除 [Authorize] 属性时,相同的调用会起作用。

我注意到 CredentialsAuthProvider 似乎可以使用 cookie(第一个响应中有几行 Set-Cookie: ...)。

第一个问题:对于非浏览器的客户端,CredentialsAuthProvider 是否是正确的选择?

显然 Fiddler 无法识别 cookie,我怎么知道 iPhone (或任何其他移动设备) 是否可以?

接下来,我尝试改用基本身份验证。
这是我的 BasicAuthProvider:

public class MyBasicAuthProvider : BasicAuthProvider
{
    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
    {
        if (request.UserName == "MyUser")
        {
            return true;
        }
    }
}

但我很困惑 - 我什至无法在浏览器中使用它。

当我在浏览器中加载我的服务的 URL 时,会弹出一个窗口并要求输入用户名和密码。
我输入正确的用户名并按回车键,同样的窗口立即再次弹出。一次又一次……如此反复,无论我输入(正确)数据的频率如何。

但是,我可以看到 ServiceStack 实际上使用了我的 MyBasicAuthProvider,因为当我在 Visual Studio 中设置断点时,我看到它识别用户名并返回 True

第二个问题:我做错了什么?

我是否需要做更多的事情才能让 Basic Auth 使用我自己的数据库?重写 Authenticate 还不够吗?

最佳答案

我将尝试回答您问题的 ServiceStack 端,但我认为您需要查看 handling authentication over HTTP以及 iPhone 应用程序如何处理 HTTP 请求/响应。另外,我认为 this provides some insight了解 ServiceStack 如何处理身份验证。

对于非浏览器的客户端,CredentialsAuthProvider 是否是正确的选择?
我认为您可以使用 Credentials 或 Basic。你需要某种类型的 Custom Authentication因为您在自己的数据库中有用户名/密码(您可以子类化 CredentialsAuthProvider 或 BasicAuthProvider 并覆盖 TryAuthenticate)。两者之间的区别在于您希望客户端(在本例中为 iPhone 应用程序)将用户名/密码放入服务的 HTTP 请求中。使用凭据,它是正文的一部分。对于 Basic,它是授权 header 的一部分。在“服务器端”,ServiceStack 将您需要执行的操作抽象为您选择的 *Provider 类/代码。

但是,当我在 Fiddler 中尝试时,我注意到相同的工作流程不起作用。
正确的。 Fiddler 不会保留 session cookie 并在后续请求中发送它们(即像浏览器那样)。使用 Fiddler 时,您需要“手动”提供它们。

第二个问题:我做错了什么
我认为 ServiceStack 没有任何启动请求身份验证的“弹出窗口”的功能。这听起来像是“集成 Windows 身份验证”问题。不过不太确定。

关于c# - 如何让 ServiceStack 身份验证工作? (使用 iPhone 客户端),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17110015/

相关文章:

c# - 如何正确处置未实现 IDisposable 的已注册 C# 服务中保存的实例?

c# - 抽象类实例化

c# - 我可以检测 ios 应用程序是否从 APN 取消注册吗

algorithm - 由 Mashery 实现的 API 签名认证是如何工作的?

c# - Observable 中的通知并行性

c# - 绑定(bind)用户和密码

.net - WSDL.exe 的位置

c# - 来自 WSDL 的 .NET 网络服务客户端

.net - 当有人试图运行我的 .net 桌面应用程序时,如何强制显示 "Run As"表单?

authentication - 两个 gitlab 安装 - 一个接受 ssh key auth,另一个不接受