如何使ServiceStack身份validation工作? (使用iPhone客户端)

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

我一般都在努力获得授权:使用何种授权以及如何实施授权。
我对ServiceStack,HTTP和授权(我)了解不多。我读过这篇文章 ,但我可能还是做错了。

我将使用现有遗留数据库中的用户名和密码进行身份validation(但没有别的 – 没有注册新用户,没有不同的权限。只是进行身份validation)。
所以我需要编写自己的提供者。

我已经设法在本教程的帮助下实现了一个有效的CredentialsAuthProvider
它在我在浏览器中测试时有效:

  • 致电我的服务并获得401
  • POST到auth/credentials
  • 再次呼叫我的服务并获得正确的结果

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

POST到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 

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

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

我注意到CredentialsAuthProvider似乎与cookie一起工作(第一个响应中有几个Set-Cookie: ...行)。

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

显然Fiddler不承认cookie,我怎么知道iPhone (或任何其他移动设备)会不会?

接下来,我尝试使用基本身份validation。
这是我的BasicAuthProvider

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

但我很难过 – 我甚至没有从浏览器中获得这个function。

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

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

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

我是否需要做更多的事情来使用我自己的数据库来运行Basic Auth? 是不是压倒一切Authenticate

我将尝试回答您的问题的ServiceStack结束,但我认为您需要考虑通过HTTP处理身份validation以及iPhone应用程序如何处理HTTP请求/响应。 此外,我认为这提供了一些有关 ServiceStack如何处理身份validation的见解 。

对于不是浏览器的客户端,CredentialsAuthProvider是否是正确的选择?
我认为你可以使用凭据或基本。 您需要某种类型的自定义身份validation,因为您在自己的数据库中有用户名/密码(您可以inheritanceCredentialsAuthProvider或BasicAuthProvider并覆盖TryAuthenticate)。 两者之间的区别在于您希望客户端(在本例中为iPhone应用程序)将用户名/密码放入您的服务的HTTP请求中。 使用凭证,它是身体的一部分。 使用Basic它是授权标题的一部分。 在“服务器端”,ServiceStack将您需要做的事情抽象到您选择的* Provider类/代码中。

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

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