我们聘请了一位为我们编写iPhone应用程序的承包商,我开始用ServiceStack为它编写后端服务。
我正在努力获得授权:使用何种授权以及如何实施授权 我对ServiceStack,HTTP和授权(我)了解不多。我读过this,但我可能还是做错了。
我将使用现有旧数据库中的用户名和密码进行身份验证(但没有别的 - 没有注册新用户,没有不同的权限。只是进行身份验证)。
所以我需要编写自己的提供者。
我已经设法在this tutorial的帮助下实施了工作CredentialsAuthProvider
它在我在浏览器中测试时有效:
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 package中的HelloService
,我刚刚添加了[Authorize]
属性
实际请求是正确的,因为当我删除[Authorize]
属性时,同样的调用会起作用。
我注意到CredentialsAuthProvider
似乎与Cookie一起使用(第一个响应中有几条Set-Cookie: ...
行。)
显然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时,会弹出一个窗口并询问用户名和密码 我输入正确的用户名并按Enter键,然后立即再次弹出相同的窗口。无论我多久输入一次(正确的)数据,再一次又一次......等等。
但是,我可以看到ServiceStack实际上使用了我的MyBasicAuthProvider
,因为当我在Visual Studio中设置断点时,我看到它识别用户名并返回True
。
我是否需要做更多工作才能使用我自己的数据库进行Basic Auth工作?是不是足以覆盖Authenticate
?
答案 0 :(得分:5)
我会尝试回答你的问题的ServiceStack结束,但我认为你需要研究handling authentication over HTTP以及iPhone应用程序如何处理HTTP请求/响应。另外,我认为this provides some insight涉及ServiceStack处理身份验证的方式。
对于不是浏览器的客户端,CredentialsAuthProvider是否是正确的选择?
我认为您可以使用凭据或基本。您需要某种类型的Custom Authentication,因为您在自己的数据库中有用户名/密码(您可以继承CredentialsAuthProvider或BasicAuthProvider并覆盖TryAuthenticate)。两者之间的区别在于您希望客户端(在本例中为iPhone应用程序)将用户名/密码放入HTTP服务请求中。凭证书,它是身体的一部分。使用Basic它是授权标题的一部分。在“服务器端”ServiceStack将您需要做的事情抽象到您选择的* Provider类/代码中。
但是,我注意到当我在Fiddler中尝试时,相同的工作流程不起作用。
正确。 Fiddler没有保留会话cookie并在后续请求中发送它们(即像浏览器一样)。使用Fiddler时,您需要“手动”提供它们。
第二个问题:我做错了什么?
我不认为ServiceStack有任何启动请求身份验证的“弹出窗口”。这听起来像是“集成Windows身份验证”问题。但不是很确定。