如何使用ASP.NET识别模型WCF服务的授权和认证 [英] How to use ASP.NET Identity Model for WCF service authorization and authentication
问题描述
我的工作,它使用ASP.NET模型身份认证和授权的ASP.NET 4.5 Web应用程序。
I am working on a ASP.NET 4.5 Web Application which uses ASP.NET Identity model for authentication and authorization.
此Web应用程序还设有一个WCF服务,并在同一时间内消耗它。有将使用这个托管WCF服务托管(与Web应用程序作为客户端本身一起),另一个基于WPF的应用程序。
This web application also hosts a WCF Service and at the same time consumes it. There is another WPF-based application which will use this hosted WCF Service hosted (along with web application as a client itself).
我想授权和验证每一个WCF服务请求(无论是从Web应用程序客户端或WPF客户端推出)。
I want to authorize and authenticate each WCF Service request (coming either from Web Application Client or WPF Client).
在理想的情况下,我想用同样的ASP.NET识别模型WCF操作契约认证/授权。如何从Web应用程序实现这一目标以及WPF应用程序?
In ideal scenario, I would like to use same ASP.NET Identity Model for authentication/authorization of WCF operation contracts. How can I achieve this from Web Application as well as WPF application?
推荐答案
您使用PrincipalPermissionAttribute装饰授权操作的实现。
You use PrincipalPermissionAttribute to decorate the operation implementation for authorization.
public class Service1 : IService1
{
public string GetData(int value)
{
System.Diagnostics.Debug.WriteLine("GetDataCalled");
if (value == 666)
throw new FaultException<Evil666Error>(new Evil666Error() { Message = "Hey, this is 666." });
return string.Format("You entered: {0}", value);
}
[PrincipalPermission(SecurityAction.Demand, Role="Admin")]
[PrincipalPermission(SecurityAction.Demand, Role="Customer")]
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
var userName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
因此,第一操作仅需要验证,而第二需求的授权
So the first operation needs only authentication, while the 2nd needs authorization.
然后,你需要编写自定义的身份验证和授权codeS。
Then you need to write custom authentication and authorization codes.
/// <summary>
/// Used in ServiceModel's ServiceBehavior for authentication of service operations.
/// </summary>
public class IdentityValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
using (var context = new WebPortalDbContext())
{
using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context)))
{
var user = userManager.Find(userName, password);
if (user == null)
{
var msg = String.Format("Unknown Username {0} or incorrect password {1}", userName, password);
Trace.TraceWarning(msg);
throw new FaultException(msg);//the client actually will receive MessageSecurityException. But if I throw MessageSecurityException, the runtime will give FaultException to client without clear message.
}
}
}
}
}
/// <summary>
/// Used in ServiceModel's ServiceBehavior for authorization of service operation, according to the role in PrincipalPermissionAttribute
/// </summary>
public class RoleAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
base.CheckAccessCore(operationContext);
using (var context = new WebPortalDbContext())
using (var userStore = new UserStore<ApplicationUser>(context))
{
using (var userManager = new UserManager<ApplicationUser>(userStore))
{
var identity =operationContext.ServiceSecurityContext.PrimaryIdentity;
var user = userManager.FindByName(identity.Name);
if (user == null)
{
var msg = String.Format("Unknown Username {0} .", user.UserName);
Trace.TraceWarning(msg);
throw new FaultException(msg);
}
//Assign roles to the Principal property for runtime to match with PrincipalPermissionAttributes decorated on the service operation.
var roleNames = userManager.GetRoles(user.Id).ToArray();//users without any role assigned should then call operations not decorated by PrincipalPermissionAttributes
operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Principal"] = new GenericPrincipal(operationContext.ServiceSecurityContext.PrimaryIdentity, roleNames);
return true;
}
}
}
}
在配置,你应该有这些将它们连接。
In the config you should have these to wire them together.
<serviceBehaviors>
<behavior name="authBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyNamespace.IdentityValidator,MyNamespace.Security" />
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="Mynamespace.Security.RoleAuthorizationManager,mynamespace.Security"></serviceAuthorization>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<service name="Fonlow.Demo.RealWorldService.Service1" behaviorConfiguration="authBehavior">
<!-- Service Endpoints. A Service may provide multiple endpoints -->
<!-- Not need to define host. Relative -->
<endpoint address="" binding="basicHttpsBinding" contract="Fonlow.Demo.RealWorldService.IService1" bindingConfiguration="httpsBindingConfig">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
这篇关于如何使用ASP.NET识别模型WCF服务的授权和认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!