【问题标题】:Check user access with custom attributes使用自定义属性检查用户访问权限
【发布时间】:2013-07-24 21:24:42
【问题描述】:

在会话中有用户信息,如何检查会话并允许访问基于提供的值之一的自定义属性修饰的方法。

所以我想做的是:

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" 可以根据会话值检查实际执行它。另外,这个验证可以在自定义属性实现中完成吗?

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    所以其他人是对的,属性本身没有任何作用。它只是您必须在服务调用生命周期中的某个时间点有意获取的元数据。

    添加检查器和服务行为的最好方法是添加检查器和服务行为,它是自动完成的,并不总是直接在每个操作中完成。最初设置的工作量更大,但它会从您的直接操作代码中获取,并可以使其应用于任何操作以检查该自定义属性。

    基本上你的属性是这样的:

    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();
            }
        }
    }
    

    然后你创建你的行为部分:

    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

    也适用于检查员:https://github.com/geersch/WcfParameterInspectors

    【讨论】:

    • 上帝保佑你做出如此全面的回应。
    【解决方案2】:

    属性只是元数据,例如标志、描述、附加信息。您需要自己处理这些信息。您可以在方法本身中执行此操作,也可以使用一些辅助类通过反射来处理它。

        // 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 类后面加上 Attribute 作为约定。例如,UserAccessAttribute

    【讨论】:

      【解决方案3】:

      不,你不能这样做(不能单独这样做),属性只不过是编译到你的代码中的元数据,它们本身不会做任何事情。一旦你用一些属性元数据装饰了一个方法或类,你就可以使用反射,比如GetCustomAttributes(typeof(UserAccess)),来检索元数据并对其采取行动,这个SO answer很好地说明了这一点

      您可以做的是,创建一个自定义方法,该方法将使用反射来检索元数据并为您执行评估,然后在 public Response Get(Request r) 中,在您执行任何操作之前您可以调用此方法,但这并不完全是你问的那种自动评估

      【讨论】:

        猜你喜欢
        • 2017-07-19
        • 2015-01-11
        • 2023-03-29
        • 2016-03-13
        • 1970-01-01
        • 2018-03-25
        • 1970-01-01
        • 1970-01-01
        • 2021-08-06
        相关资源
        最近更新 更多