我有一个带有邮件安全性和用户名凭据的WCF服务。我的大多数方法都是以
开头的[PrincipalPermission(SecurityAction.Demand, Role = ConstStrings.Roles.Admin)]
并且这些方法应该仅由经过身份验证的用户调用。
我想添加一个匿名调用的方法,但收到错误:
未提供用户名。在ClientCredentials中指定用户名。
我喜欢类似于MVC的[AllowAnonymous]
属性
答案 0 :(得分:7)
一种选择是实施您自己的ServiceAuthorizationManager
并使用您自己的自定义属性而不是PrincipalPermission
基本上,您必须继承ServiceAuthorizationManager
。通过在web.config中添加以下配置,将其插入到WCF管道中(假设您的类在Org.Namespace命名空间中被调用' CustomAuthorizationManager'。
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<!--<serviceAuthorization impersonateCallerForAllOperations="true" />-->
<serviceAuthorization serviceAuthorizationManagerType="Org.Namespace.CustomAuthorizationManager, Org.Namespace" />
</behavior>
</serviceBehaviors>
</behaviors>
在自定义授权类中,您必须覆盖CheckAccessCore
方法,如下所示。在那里,您可以检查您创建的自定义属性(这将是您将使用您想要的任何属性创建的普通.Net属性。)
protected override bool CheckAccessCore(OperationContext operationContext)
{
string action = operationContext.IncomingMessageHeaders.Action;
DispatchOperation operation = operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o => o.Action == action);
Type hostType = operationContext.Host.Description.ServiceType;
MethodInfo method = hostType.GetMethod(operation.Name);
var myCustomAttributeOnMethod = method.GetCustomAttributes(true).Where(a => a.GetType() == typeof (MyCustomAttribute)).Cast<MyCustomAttribute>();
.
.
.
}
现在您可以检查自定义属性并根据需要执行任何功能。例如,如果自定义属性&#34; AllowAnonymous&#34;标志已设置,您可以跳过角色检查。否则,您可能会获得用户的Windows身份并检查他们是否处于特定角色。
当然,您需要使用自定义属性而不是PrincipalPermission来装饰相关方法。
总而言之,基本上您正在使用自己的普通自定义.Net属性来装饰所有方法,该属性提供了一些信息。即此方法允许匿名,此方法需要此角色等。然后,您更新web.config文件以告知WCF使用您自己的服务授权管理器。您可以实现自己的服务授权管理器,您可以访问正在调用的方法,检查它的自定义属性并说出&#34; Yay&#34;或者&#34; Nay&#34;相应
答案 1 :(得分:1)
您可以按照上面的建议进行操作,然后使用此代码段检查调用的特定方法:
var requestedOperation =
OperationContext.Current.IncomingMessageHeaders.Action.Split('/').Last();
这将产生以下结果:
public override void Validate(string userName, string password)
{
if(String.IsNullOrEmpty(userName) && String.IsNullOrEmpty(password))
{
var requestedOperation =
OperationContext.Current.IncomingMessageHeaders.Action.Split('/').Last();
if("myAnonymousOperation" == requestedOperation)
{
// Allow anonymous access here.
return;
}
}
// Allow/deny users that provide credentials
ValidateOtherCredentials(userName, password);
}
答案 2 :(得分:0)
您可以实现this教程中显示的自定义UserNamePasswordValidator
。此验证器需要实现Validate
方法,以允许匿名访问。
public override void Validate(string userName, string password)
{
if(String.IsNullOrEmpty(userName) && String.IsNullOrEmpty(password))
{
// Allow anonymous access here.
return;
}
// Allow/deny users that provide credentials
ValidateOtherCredentials(userName, password);
}
注意:如果您允许匿名访问,则使用PrincipalPermission
的授权过程仍需要凭据。我不确定,但这可能会在运行时导致异常。