C# WCF 用户名身份验证:我可以在自定义 ServiceAuthorizationManager 中获取用户名吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/529485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:54:13  来源:igfitidea点击:

WCF UserName Authentication: Can I get the Username in a custom ServiceAuthorizationManager?

c#.netwcfauthorization

提问by CodingWithSpike

I have a WCF service that is using a custom ServiceAuthorizationManager. The custom auth manager is already set up to handle Windows and Forms authentication.

我有一个使用自定义ServiceAuthorizationManager. 自定义身份验证管理器已设置为处理 Windows 和表单身份验证。

However, if I connect with a client that is set to UserNameauth, I can't seem to find the username anywhere.

但是,如果我连接到设置为UserNameauth的客户端,我似乎无法在任何地方找到用户名。

The client code looks like this:

客户端代码如下所示:

this.ClientCredentials.UserName.UserName = "user";
this.ClientCredentials.UserName.Password = "pass";
this.Open();
this.MyMethod(); // my actual contract method
this.Close();

Then on the server, I have my custom auth manager:

然后在服务器上,我有我的自定义身份验证管理器:

public sealed class AppAuthorizationManager : ServiceAuthorizationManager
{
    public override bool CheckAccess(OperationContext operationContext, ref Message message)
    {
        // would like to check user/pwd here...
    }
}

Is this possible?

这可能吗?

  • The Thread.CurrentPrincipalis not set,
  • operationContext.ServiceSecurityContext.PrimaryIdentityis not set.
  • operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSetsis empty.
  • Thread.CurrentPrincipal未设置,
  • operationContext.ServiceSecurityContext.PrimaryIdentity未设置。
  • operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets是空的。

Is the user/pwd supposed to be available anywhere? Or do I have to add a custom UsernamePasswordValidatortoo?

用户/密码是否应该在任何地方可用?还是我也必须添加自定义UsernamePasswordValidator



Update:So I added a custom UserNamePasswordValidatorand an IAuthorizationPolicy. My updated WCF config looks like this:

更新:所以我添加了一个自定义UserNamePasswordValidator和一个IAuthorizationPolicy. 我更新的 WCF 配置如下所示:

<behavior name="Server2ServerBehavior">
  <serviceMetadata httpGetEnabled="true" />
  <serviceDebug includeExceptionDetailInFaults="true" />
  <serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="MyApp.AuthManager, MyApp">
    <authorizationPolicies>
      <add policyType="MyApp.TokenAuthorizationPolicy, MyApp" />
    </authorizationPolicies>
  </serviceAuthorization>
  <serviceCredentials>
    <userNameAuthentication customUserNamePasswordValidatorType="MyApp.PFUserNameValidator, MyApp" />
  </serviceCredentials>
</behavior>

If I set a breakpoint in all 3 of those classes, WCF throws the exception:

如果我在所有 3 个类中设置断点,WCF 将引发异常:

LogonUser failed for the 'username' user. Ensure that the user has a valid Windows account.
   at System.IdentityModel.Selectors.WindowsUserNameSecurityTokenAuthenticator.ValidateUserNamePasswordCore(String userName, String password)

Before any of them are run. Hmmm...

在它们中的任何一个运行之前。嗯...

采纳答案by Marc Gravell

This is normally handled in the UsernamePasswordValidator- which is the only place you'll have access to the password. However, this isn't where you set the principal - that would be in the IAuthorizationPolicy's Evaluatemethod, which might look something like:

这通常在UsernamePasswordValidator 中处理- 这是您可以访问密码的唯一地方。但是,这不是您设置主体的地方 - 将在IAuthorizationPolicy'sEvaluate方法中,它可能看起来像:

bool IAuthorizationPolicy.Evaluate(
    EvaluationContext evaluationContext, ref object state)
{           
    IList<IIdentity> idents;
    object identsObject;
    if (evaluationContext.Properties.TryGetValue(
        "Identities", out identsObject) && (idents =
        identsObject as IList<IIdentity>) != null)
    {
        foreach (IIdentity ident in idents)
        {
            if (ident.IsAuthenticated &&
                ident.AuthenticationType == TrustedAuthType)
            {                           
                evaluationContext.Properties["Principal"]
                    = //TODO our principal
                return true;
            }
        }
    }
    if (!evaluationContext.Properties.ContainsKey("Principal"))
    {
        evaluationContext.Properties["Principal"] = //TODO anon
    }                
    return false;
}

(where TrustedAuthTypeis the name of our password validator)

TrustedAuthType我们的密码验证器的名称在哪里)

With this in place, the thread's principal will be set, and we can identify ourselves (and use roles-based security etc)

有了这个,线程的主体将被设置,我们可以识别自己(并使用基于角色的安全等)