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
WCF UserName Authentication: Can I get the Username in a custom ServiceAuthorizationManager?
提问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 UserName
auth, I can't seem to find the username anywhere.
但是,如果我连接到设置为UserName
auth的客户端,我似乎无法在任何地方找到用户名。
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.CurrentPrincipal
is not set, operationContext.ServiceSecurityContext.PrimaryIdentity
is not set.operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets
is 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 UsernamePasswordValidator
too?
用户/密码是否应该在任何地方可用?还是我也必须添加自定义UsernamePasswordValidator
?
Update:So I added a custom UserNamePasswordValidator
and 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 Evaluate
method, 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 TrustedAuthType
is 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)
有了这个,线程的主体将被设置,我们可以识别自己(并使用基于角色的安全等)