使用ServiceStack使用REST Web服务时的用户身份验证

时间:2012-12-09 12:21:27

标签: c# json web-services authentication servicestack

ServiceStack文档中有很多关于如何使用服务器端实现用户身份验证的示例。但是如何在客户端设置用户凭据呢?

我使用ServiceStack来使用JSON REST这样的服务:

var restClient = new JsonServiceClient (baseUri);
var response = restClient.Get<MyResponse> ("/some/service");

如何在请求中添加任何形式的身份验证?我想要使​​用的网络服务使用OAuth 1.0,但我也有兴趣添加自定义身份验证。

在我的代码中,我之前已成功执行OAuth令牌交换,因此我已拥有有效的访问令牌,并且现在需要使用此访问令牌及其token_secret对每个REST请求进行签名。

2 个答案:

答案 0 :(得分:8)

ServiceStack的AuthTests在使用ServiceStack服务客户端时显示了不同的身份验证方式。默认情况下,BasicAuth和DigestAuth内置于客户端中,例如:

var client = new JsonServiceClient(baseUri) {
    UserName = UserName,
    Password = Password,
};

var request = new Secured { Name = "test" };
var response = client.Send<SecureResponse>(request);    

幕后服务ServiceStack将尝试正常发送请求,但当请求被拒绝并被服务器质询时,客户端将自动重试相同的请求,但这次使用Basic / Digest Auth标头。

要在知道您正在访问安全服务时跳过额外的跃点,您可以告诉客户端始终使用以下命令发送BasicAuth标头:

client.AlwaysSendBasicAuthHeader = true;

验证的另一种方法是显式调用Auth服务(这需要启用CredentialsAuthProvider),例如:

var authResponse = client.Send<AuthResponse>(new Auth {
    provider = CredentialsAuthProvider.Name,
    UserName = "user",
    Password = "p@55word",
    RememberMe = true,  //important tell client to retain permanent cookies
});

var request = new Secured { Name = "test" };
var response = client.Send<SecureResponse>(request);    

成功调用Auth服务后,客户端已通过身份验证,如果设置了 RememberMe ,客户端将保留服务器在后续请求中添加的会话Cookie,这是启用的来自该客户端的未来请求将被认证。

答案 1 :(得分:7)

回答我自己,因为我找到了一个很好的方法来使用LocalHttpWebRequestFilter中的JsonServiceClient挂钩:

为了使用OAuth 1.0a保护Web服务,每个http请求都必须发送一个特殊的Authorization:标头。在此标头字段中,必须发送散列(签名),该散列使用请求的某些特征作为输入数据,如主机名,请求URL和others

现在似乎在http请求发出前由ServiceStack调用LocalHttpWebRequestFilter,并公开底层HttpWebRequest对象,其中可以添加额外的标头并访问请求的必需字段。

所以我的解决方案现在基本上是:

var client = new JsonServiceClient (baseUri);

client.LocalHttpWebRequestFilter += (request) => {
    // compute signature using request and a previously obtained
    //  access token 
    string authorization_header = CalculateSignature (request, access_token);

    request.Headers.Add ("Authorization", authorization_header);
};
var response = client.Get<MySecuredResponse> ("/my/service");

请注意,我使用Devdefined.OAuth库来完成CalculateSignature()中的所有繁重内容。在上述服务调用之前,创建请求令牌,获取用户授权以及根据OAuth要求交换访问令牌的请求令牌是在ServiceStack之外完成的。