使用自定义属性检查用户访问权

use*_*567 9 c# wcf

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

所以我要做的是:

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

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

    }
}
Run Code Online (Sandbox Code Playgroud)

然后当我装饰这样的端点时:

[UserAccess(userRole = "Residents")]
public Response Get(Request r){
    ///-- Implementation
}
Run Code Online (Sandbox Code Playgroud)

以某种方式调用端点时,只能userRole = "Residents"基于会话值检查实际执行它.此外,可以在自定义属性实现中完成此验证吗?

Chr*_*rda 18

所以其他人都是对的,这些属性本身没有任何作用.在服务调用的生命周期中,您必须特意获取元数据.

这样做的最佳方式是自动神奇地完成并且并非总是直接在每个操作中添加检查器和服务行为.最初进行设置需要做更多的工作,但它可以从您的直接操作代码中获取,并且可以使其应用于检查该自定义属性的任何操作.

基本上你有这样的属性:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后设置端点行为(您可以使用其他行为):

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您创建您的行为部分:

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


        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后设置配置以使用新行为:

<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>
Run Code Online (Sandbox Code Playgroud)

这是服务接口 - 有一个操作可以工作,另一个操作由于用户访问错误而失败

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

    }



}
Run Code Online (Sandbox Code Playgroud)

和服务业务:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅MSDN http://msdn.microsoft.com/en-us/library/ms730137.aspx

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