servicestack,basic-authentication,C#,Web Services,Authentication,servicestack,Basic Authentication" /> servicestack,basic-authentication,C#,Web Services,Authentication,servicestack,Basic Authentication" />

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

C# 如何让ServiceStack身份验证工作?(使用iPhone客户端),c#,web-services,authentication,servicestack,basic-authentication,C#,Web Services,Authentication,servicestack,Basic Authentication,我们已经聘请了一名承包商,他正在为我们编写一个iPhone应用程序,我正在开始用ServiceStack为其编写后端服务 一般来说,我正在与授权作斗争:使用什么样的授权以及如何实现它。 我对ServiceStack、HTTP和授权知之甚少。。我读过,但我可能还是做错了什么 我将使用现有遗留数据库中的用户名和密码进行身份验证(但除此之外,无需注册新用户,无需其他权限。只需进行身份验证)。 所以我需要编写自己的提供者 在的帮助下,我成功地实现了一个有效的CredentialAuthProvider。

我们已经聘请了一名承包商,他正在为我们编写一个iPhone应用程序,我正在开始用ServiceStack为其编写后端服务

一般来说,我正在与授权作斗争:使用什么样的授权以及如何实现它。
我对ServiceStack、HTTP和授权知之甚少。。我读过,但我可能还是做错了什么

我将使用现有遗留数据库中的用户名和密码进行身份验证(但除此之外,无需注册新用户,无需其他权限。只需进行身份验证)。
所以我需要编写自己的提供者

在的帮助下,我成功地实现了一个有效的
CredentialAuthProvider

当我在浏览器中测试它时,它会工作:

  • 打电话给我的服务部,申请401
  • 发布到
    auth/credentials
  • 再打电话给我的服务,得到正确的结果
然而,当我在Fiddler中尝试时,我注意到相同的工作流不起作用

发到
auth/credentials
的帖子有效。我发了这封信:

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
(这是来自的
HelloService
,我刚刚添加了
[Authorize]
属性)

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

我注意到,
credentialauthProvider
似乎可以处理Cookie(在第一个响应中有几个
Set Cookie:…
行)

第一个问题:对于不是浏览器的客户端来说,CredentialAuthProvider是正确的选择吗? 显然Fiddler不识别cookies,我如何知道iPhone(或任何其他移动设备)是否会识别cookies?

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

public class MyBasicAuthProvider : BasicAuthProvider
{
    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
    {
        if (request.UserName == "MyUser")
        {
            return true;
        }
    }
}
但是我被难住了——我甚至不能从浏览器上使用它

当我在浏览器中加载服务的URL时,会弹出一个窗口,询问用户名和密码。
我输入正确的用户名并按enter键,同一个窗口立即再次弹出。一次又一次……等等,不管我多久输入一次(正确的)数据

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

第二个问题:我做错了什么?
我是否需要做更多的事情才能使用我自己的数据库使用Basic Auth?覆盖
身份验证
还不够吗?

我将尝试回答您问题的ServiceStack结尾,但我认为您需要了解iPhone应用程序如何处理HTTP请求/响应。此外,我还考虑了ServiceStack如何处理身份验证

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

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

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

我不认为ServiceStack有任何启动“弹出窗口”请求身份验证的功能。这听起来像是“集成Windows身份验证”问题。不过,我不太确定

我决定坚持基本的身份验证。我的BasicAuthProvider现在可以工作了(问题是我需要覆盖
tryaauthenticate
,而不是
Authenticate
)。顺便说一句,请求验证的弹出窗口是浏览器在涉及基本验证时立即打开的标准窗口。我知道这是一个老问题,但不是使用会话cookie,可以使用标题:“您现在可以使用HTTP标题而不是Cookie发出启用会话的请求。会话HTTP标题在会话Id之前有一个X前缀,即:X-ss-Id、X-ss-pid和X-ss-opts。”,但我不确定这是否在SSv3中可用,这是来自最新文档(商业v4)。