c# - 如何在 ServiceAuthorizationManager 中设置身份/用户名?

标签 c# .net wcf wcf-security

我在服务器端(托管在 IIS 中)和 Android 客户端上有一个 WCF 4.0 REST 服务。 Android 客户端在自定义 HTTP header 中发送加密的安全 token ,以对用户进行身份验证。我已经实现了一个自定义 ServiceAuthorizationManager,它从 header 中提取安全 token 。 token 包含我可以从 token 中读取的用户名:

public class MyAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        var requestMessage = operationContext.RequestContext.RequestMessage;
        var requestProperty = (HttpRequestMessageProperty)requestMessage
            .Properties[HttpRequestMessageProperty.Name];
        var token = requestProperty.Headers["X-MyCustomHeader"];
        if (!string.IsNullOrEmpty(token))
        {
            var userName = GetUserNameFromToken(token);
            if (!string.IsNullOrEmpty(userName))
            {
                // How to save userName now so that I can 
                // retrieve it in the service operations?
                return true;
            }
        }
        return false;
    }
}

现在,我的问题是在各种服务操作(主要是访问用户配置文件数据)中我还需要经过身份验证的用户的名称,我正计划以这种方式检索它:

public void MyServiceOperation()
{
    string userName = OperationContext.Current
        .ServiceSecurityContext.PrimaryIdentity.Name;

    // check profile store for that userName and do something depending on
    // profile settings
}

如何在 CheckAccessCore 中设置此用户名?

像这样一个非常天真的试验......

operationContext.ServiceSecurityContext.PrimaryIdentity.Name = userName;

...不起作用,因为 PrimaryIdentity.Name 是只读的。我假设需要更复杂的代码。

最佳答案

经过一些研究,我没有找到在 ServiceAuthorizationManager.CheckAccessCore 中设置身份的方法。当用户身份已设置(可能为“匿名”(IsAuthenticatedfalse))且无法再更改时,此方法似乎在处理管道中被调用得太迟. ServiceAuthorizationManager 用于授权,而不是身份验证,因此它不是实现自定义身份验证的错误位置。

我终于找到了三种可能的方法来解决我的问题:

  1. 如@TheCodeKing 的回答中链接的文章中所述,使用 WCF REST 初学者工具包提供了编写自定义 RequestInterceptor 的选项,它足够早地挂接到管道中,允许访问传入请求并允许根据自定义 HTTP header 等设置用户身份。不幸的是,WCF REST Starter Kit 很旧(基于 WCF 3.5)并且开发显然已被放弃。它的一些特性已经被合并到 WCF 4.0 中,但有些还没有,RequestInterceptor 就是其中之一。尽管如此,我现在已经使用了这个解决方案并将初学者工具包中的 Microsoft.ServiceModel.Web 程序集混合到我的 WCF 4.0 解决方案中。经过一些简单的测试,它似乎到目前为止有效。

  2. 如果身份不是真正必需的,而只是用户名,那么将用户名写入新请求 header 的简单“技巧”/“hack”就可以了(也在 CheckAccessCore 中) ):

    // ...
    var userName = GetUserNameFromToken(token);
    if (!string.IsNullOrEmpty(userName))
    {
        requestProperty.Headers["X-UserName"] = userName;
        return true;
    }
    // ...
    

    然后在服务方法中:

    public void MyServiceOperation()
    {
        string userName = WebOperationContext.Current.IncomingRequest
            .Headers["X-UserName"];
        // ...
    }
    
  3. 另一个更底层的选项是编写一个自定义 HttpModule,它拦截传入的请求并设置身份。这看起来像的一个例子是 here来自 Microsoft Pattern & Practices 团队(参见文章中间的“HTTP 模块代码”示例)。

关于c# - 如何在 ServiceAuthorizationManager 中设置身份/用户名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7299922/

相关文章:

c# - 字符串连接与字符串生成器。表现

c# - 嵌套 for 循环的动态数量,用于列出对象的唯一组合

.net - 如何使用Grails调用WCF .net Web服务

c# - 将 IdentityServer4 配置为仅颁发 token

c# - 等待异步 WCF 方法

c# - Linux 上带有单声道的 ServiceStack

c# - 为什么 BindNever 属性不起作用

c# - caliburn.micro 导体不工作

c# - 如何将参数传递给带有特殊字符的 WCF Web 服务?

session 之间的 WCF 数据持久化