2013-07-24 32 views
5

在Session中拥有用户信息时,如何根据提供的值之一检查会话并允许访问使用自定义属性装饰的方法。使用自定义属性检查用户访问

那么我现在要做的是:

public class UserAccess: System.Attribute 
{ 
    private string userRole; 

    public UserAccess(string userRole) 
    { 
     this.userRole = userRole; 

    } 
} 

后来,当我布置这样的端点:调用端点

[UserAccess(userRole = "Residents")] 
public Response Get(Request r){ 
    ///-- Implementation 
} 

不知怎的,当只有userRole = "Residents"能够实际执行它基于在会话值检查。另外,这个验证可以在自定义属性实现中完成吗?

回答

17

所以其他人是正确的,即属性自己什么都不做。这只是元数据,您必须在服务调用的整个生命周期中有意识地获取元数据。

要做到这一点,最好的方法是自动完成,而不总是直接在每个操作中完成,就是添加检查器和服务行为。初始设置需要更多的工作,但它可以从您的直接操作代码中获取,并且可以使其适用于检查该自定义属性的任何操作。

基本上,你有你的属性,像这样:

namespace MyCustomExtensionService 
{ 
    public class UserAccessAttribute : System.Attribute 
    { 
     private string _userRole; 

     public UserAccessAttribute(string userRole) 
     { 
      _userRole = userRole; 

      //you could also put your role validation code in here 

     } 

     public string GetUserRole() 
     { 
      return _userRole; 
     } 
    } 
} 

然后您设置的参数检查(注意有其他检查人员可以使用):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.ServiceModel; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using System.Web; 

namespace MyCustomExtensionService 
{ 
    public class MyParameterInspector : IParameterInspector 
    { 

     public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) 
     { 
      //throw new NotImplementedException(); 
     } 

     public object BeforeCall(string operationName, object[] inputs) 
     { 
      MethodInfo method = typeof(Service1).GetMethod(operationName); 
      Attribute[] attributes = Attribute.GetCustomAttributes(method, typeof(UserAccessAttribute), true); 

      var attr = (UserAccessAttribute)attributes.First(); 

      if (attributes.Any()) 
      { 
       var userHasProperAuthorization = true; 
       if (attr.GetUserRole() == "Residents" && userHasProperAuthorization) 
       { 
        //everything is good, continue to operation 
       } 
       else 
       { 
        throw new FaultException("You do not have the right security role!"); 
       } 
      } 



      return null; 

     } 
    } 
} 

然后你设置你的终结点行为(还有其他行为可以使用):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using System.Web; 

namespace MyCustomExtensionService 
{ 
    public class MyCustomAttributeBehavior : IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
     { 
      //throw new NotImplementedException(); 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
     { 
      foreach (ClientOperation clientOperation in clientRuntime.Operations) 
      { 
       clientOperation.ParameterInspectors.Add(
        new MyParameterInspector()); 
      } 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
     { 
      foreach (DispatchOperation dispatchOperation in endpointDispatcher.DispatchRuntime.Operations) 
      { 

       dispatchOperation.ParameterInspectors.Add(
        new MyParameterInspector()); 
      } 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
      //throw new NotImplementedException(); 
     } 
    } 
} 

然后你创建y我们的行为部分:

using System.Linq; 
using System.ServiceModel.Configuration; 
using System.Web; 

namespace MyCustomExtensionService 
{ 
    public class MyBehaviorSection : BehaviorExtensionElement 
    { 

     protected override object CreateBehavior() 
     { 
      return new MyCustomAttributeBehavior(); 

     } 

     public override Type BehaviorType 
     { 

      get { return typeof(MyCustomAttributeBehavior); } 


     } 
    } 
} 

然后你设置为使用新的行为的配置:

<system.serviceModel> 
    <services> 
     <service name ="MyCustomExtensionService.Service1"> 
     <endpoint address="" behaviorConfiguration="MyCustomAttributeBehavior" 
      binding="basicHttpBinding" contract="MyCustomExtensionService.IService1"> 
     </endpoint> 
     </service> 
    </services> 
    <extensions> 
     <behaviorExtensions> 
     <add name="Validator" type="MyCustomExtensionService.MyBehaviorSection, MyCustomExtensionService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
     </behaviorExtensions> 
    </extensions> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="MyCustomAttributeBehavior"> 
      <Validator /> 
     </behavior> 
     </endpointBehaviors> 

这里的服务界面 - 通过一项操作,将工作和一个将失败的原因具有错误的用户访问

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Text; 

namespace MyCustomExtensionService 
{ 

    [ServiceContract] 
    public interface IService1 
    { 

     [OperationContract] 
     string GetData(int value); 

     [OperationContract] 
     string GetDataUsingWrongUserAccess(int value); 

    } 



} 

,服务操作:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.Text; 

namespace MyCustomExtensionService 
{ 

    public class Service1 : IService1 
    { 
     [UserAccess("Residents")] 
     public string GetData(int value) 
     { 
      return string.Format("You entered: {0}", value); 
     } 

     [UserAccess("Admin")] 
     public string GetDataUsingWrongUserAccess(int value) 
     { 
      return string.Format("You entered: {0}", value); 
     } 
    } 
} 

欲了解更多信息,请参阅MSDN http://msdn.microsoft.com/en-us/library/ms730137.aspx

也检查员:http://cgeers.com/2008/11/09/wcf-extensibility-parameter-inspectors/

+0

哇..这是很多代码..谢谢 – user1791567

+1

上帝保佑你这样一个全面的回应。 – Jeremy

0

不,你不能这样做(不是自己),属性只不过是编译到代码中的元数据,它们本身并没有做任何事情。一旦你装饰了一些属性的元数据的方法或类,然后你可以使用反射,像GetCustomAttributes(typeof(UserAccess)),检索在它的元数据和行为,这SO answer说明了这一点很好

你可以做的是,创建一个自定义方法将使用反射检索元数据并为您进行评估,然后在public Response Get(Request r)之内,在您执行任何可以调用此方法之前,但这不完全是您要求的自动评估类型

+0

同意..我想我最好的对象了会议,并评估它... – user1791567

1

属性为仅仅是元数据,如标志,描述,附加信息。你需要自己处理这些信息。您可以在方法本身中执行此操作,或者使用反射来处理它。

// Using reflection. 
    MethodInfo method = typeof(ClassName).GetMethod("Get"); 
    Attribute[] attributes = Attribute.GetCustomAttributes(method, typeof(UserAccess), true); 


    // Displaying output. 
    foreach (var attr in attributes) 
    { 
     if (attr is UserAccess) 
     { 
      var ua = (UserAccess)attr; 
      System.Console.WriteLine("{0}",a.userRole); 
     } 
    } 

*我也建议这个词属性后缀添加到UserAccess类作为一个惯例。例如,UserAccessAttribute

+0

这是一个值得考虑..谢谢 – user1791567