c# - contraseña - Autenticación WCF UserName: ¿Puedo obtener el nombre de usuario en un ServiceAuthorizationManager personalizado?
autenticacion wcf c# (1)
Esto normalmente se maneja en UsernamePasswordValidator , que es el único lugar donde tendrá acceso a la contraseña. Sin embargo, aquí no es donde configura el principal, eso sería en el método Evaluate
IAuthorizationPolicy
, que podría verse más o menos así:
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;
}
(donde TrustedAuthType
es el nombre de nuestro validador de contraseñas)
Con esto en su lugar, se establecerá el principio del hilo, y podemos identificarnos (y usar la seguridad basada en roles, etc.)
Tengo un servicio WCF que está usando un ServiceAuthorizationManager
personalizado. El administrador de autenticación personalizado ya está configurado para manejar la autenticación de Windows y Formularios.
Sin embargo, si me conecto con un cliente que está configurado para la autenticación de nombre de usuario, parece que no puedo encontrar el nombre de usuario en ninguna parte.
El código del cliente se ve así:
this.ClientCredentials.UserName.UserName = "user";
this.ClientCredentials.UserName.Password = "pass";
this.Open();
this.MyMethod(); // my actual contract method
this.Close();
Luego, en el servidor, tengo mi administrador de autenticación personalizado:
public sealed class AppAuthorizationManager : ServiceAuthorizationManager
{
public override bool CheckAccess(OperationContext operationContext, ref Message message)
{
// would like to check user/pwd here...
}
}
es posible?
- El
Thread.CurrentPrincipal
no está configurado, -
operationContext.ServiceSecurityContext.PrimaryIdentity
no está configurado. -
operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets
está vacío.
¿Se supone que el usuario / pwd estará disponible en cualquier lugar? ¿O debo agregar un UsernamePasswordValidator
personalizado también?
Actualización: Así que agregué un UserNamePasswordValidator
personalizado y una IAuthorizationPolicy
. Mi configuración de WCF actualizada se ve así:
<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>
Si establezco un punto de interrupción en las 3 de esas clases, WCF arroja la excepción:
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)
Antes de ejecutar cualquiera de ellos. Hmmm ...