2013-07-24 31 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