OData V4客户端代码生成器并处理401响应

时间:2015-07-14 14:36:41

标签: c# authentication odata odata-v4

我有一个使用自定义身份验证机制的WebAPI 2.2 w / OData V4服务。基本上它类似于OAuth的承载认证,因此使用用户名和密码向特定端点发出请求并返回令牌。然后,令牌将包含在所有后续请求的Authorization标头中。 我正在使用OData V4客户端代码生成器(2.3.0)并使用DataServiceContext的BuildingRequest事件手动添加Authorization标头,如此...

private void GetData() {
    var context = new DataAccess.Default.Container(new Uri("http://myserver/API/"));

    context.BuildingRequest += onBuildingRequest;
    var data = context.Computers.ToList();
}
void onBuildingRequest(object sender, Microsoft.OData.Client.BuildingRequestEventArgs e)
{
    if (_token == null)
        _token = GetToken();
    e.Headers.Add("Authorization", "MyToken " + _token);
}

我遇到的问题是令牌在一段时间后过期,所以一段时间后我会开始得到一个401响应,这会导致异常从上下文获取IQueryables得到他们的GetEnumerator被调用(上面代码中的ToList调用)。我可以包装我枚举端点的每个地方,但这不太理想。 我发现我可以在DataServiceContext的ReceivingResponse事件中检测到401,并标记该令牌已过期,但是这不会阻止调用失败,只会使后续调用工作。

void context_ReceivingResponse(object sender, ReceivingResponseEventArgs e)
{
    if (e.ResponseMessage.StatusCode == 401)
    {
        _token = null;
    }
}

所以在这一点上,我试图找出一种处理401的方法,而不需要每次调用(通常在枚举IQueryable时)将其包装在try / catch中。我试图想办法让Web请求以类似于处理基本身份验证的方式处理我的自定义身份验证(如果服务器响应401和WWW-Authenticate头,并且已为基本身份验证指定了凭据另一个请求将自动发送所需的身份验证标头)但没有运气。

任何帮助/建议都将不胜感激。

2 个答案:

答案 0 :(得分:1)

解决方案位于AuthenticaionManager级。通过IAuthenticationModule方法注册您自己的Register实施,您将能够做您正在寻找的事情。

您还可能需要另一个实现ICredentials的类并处理您的身份验证参数,例如您的令牌端点网址等,然后将其传递给您的DataServiceContext。您甚至可以使用它来缓存最后一个令牌及其到期时间。

到目前为止我找到的处理过期令牌的唯一方法是在从授权服务器获取令牌时存储到期时间,并且如果它已接近过期则刷新它即可。并且通过"关闭" 我的意思是它是否会在n秒内过期。我更喜欢将此阈值作为检索令牌的网络超时。如果它已经过期甚至接近过期,我将从服务器获得一个新令牌,甚至没有尝试最后一个令牌。请在本节中随意使用您需要的任何测量值。 ;)但是没有办法不止一次地响应授权服务器的挑战,它不会永远地挑战你。

请查看here以获取有关所提及的类和接口的示例。

BTW在Portable Class Library中使用它可能会有点运气不好。 pcl中没有AuthenticaionManagerIAuthenticationModule的迹象。使用某种抽象可能有所帮助。

答案 1 :(得分:0)

也许您忘了在GetData中挂钩context_ReceivingResponse? (我没看到) 否则,请在发送和接收事件中记录http-header以确保。