在IAuthorizationPolicy中获取服务实例

4
通常,您可以像这样从OperationContext中获取服务实例:获取服务实例
OperationContext.Current.InstanceContext.GetServiceInstance()

然而,当你在IAuthorizationPolicy中时,InstanceContext为null。是否有其他方法可以在IIS托管时获取服务实例?


根据我对 IAuthorizationPolicyServiceAuthorizationManager 的观察,只有在通过调用 ServiceAuthorizationManager.CheckAccess 并返回 true 授权给用户后,服务的实例才会被创建。考虑到 CheckAccess 调用了 CheckAccessCore 并最终调用了 IAuthorizationPolicy.Evaluate,我不确定你所要求的是否可能,至少对于一个 PerSession 服务而言是如此。 - user585968
@MickyDuncan:谢谢,我担心会是这种情况。有没有可能有一个显示事件流的参考资料呢? - zimdanen
这里有一篇不错的文章:[http://pfelix.wordpress.com/2008/08/06/the-serviceauthorizationmanager-class-in-wcf/ ] - user585968
@MickyDuncan:谢谢,但是那篇文章似乎没有将授权放在服务生命周期的背景下进行讨论。 - zimdanen
2个回答

7
IAuthorizationPolicy.Evaluate()中,OperationContext.Current.InstanceContext并不总是为null。
Carlos Figueira的WCF可扩展性测试程序开始,该程序在每次调用WCF扩展时向命令行输出一条消息。我添加了一个自定义的IAuthorizationPolicy。以下是输出和程序。
输出显示:
1. IAuthorizationPolicy.Evaluate()在服务实例创建后被调用。 2. IAuthorizationPolicy.Evaluate()中的OperationContext.Current.InstanceContext不为null。
该测试程序使用BasicHttpBinding进行自助式托管。在其他托管环境中,IAuthorizationPolicy.Evaluate()可能无法访问服务实例,但这至少在理论上是可能的。
为什么要这样做?
从架构角度来看,IAuthorizationPolicy应处理声明。应用程序应使用ClaimsPrincipal上的声明。将IAuthorizationPolicy紧密耦合到特定服务会破坏Windows标识体系结构中有意的关注点分离。换句话说,我认为这是一个坏主意。
测试程序是一个Windows命令行程序,所有内容都在一个文件中。
using System;
using System.Globalization;
using System.IdentityModel.Claims;
using System.IdentityModel.Policy;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading;
using System.Collections.Generic;

namespace WcfRuntime
{
    class MyDispatchMessageInspector : IDispatchMessageInspector
    {
        public MyDispatchMessageInspector()
        {
        }

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return null;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }
    }

    class MyDispatchMessageFormatter : IDispatchMessageFormatter
    {
        IDispatchMessageFormatter inner;
        public MyDispatchMessageFormatter(IDispatchMessageFormatter inner)
        {
            this.inner = inner;
        }

        public void DeserializeRequest(Message message, object[] parameters)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            this.inner.DeserializeRequest(message, parameters);
        }

        public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.SerializeReply(messageVersion, parameters, result);
        }
    }

    class MyClientMessageInspector : IClientMessageInspector
    {
        public MyClientMessageInspector()
        {
        }

        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return null;
        }
    }

    class MyClientMessageFormatter : IClientMessageFormatter
    {
        IClientMessageFormatter inner;
        public MyClientMessageFormatter(IClientMessageFormatter inner)
        {
            this.inner = inner;
        }

        public object DeserializeReply(Message message, object[] parameters)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.DeserializeReply(message, parameters);
        }

        public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.SerializeRequest(messageVersion, parameters);
        }
    }

    class MyDispatchOperationSelector : IDispatchOperationSelector
    {
        public string SelectOperation(ref Message message)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            string action = message.Headers.Action;
            string method = action.Substring(action.LastIndexOf('/') + 1);
            return method;
        }
    }

    class MyParameterInspector : IParameterInspector
    {
        ConsoleColor consoleColor;
        bool isServer;
        public MyParameterInspector(bool isServer)
        {
            this.isServer = isServer;
            this.consoleColor = isServer ? ConsoleColor.Cyan : ConsoleColor.Yellow;
        }

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
            ColorConsole.WriteLine(this.consoleColor, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }

        public object BeforeCall(string operationName, object[] inputs)
        {
            ColorConsole.WriteLine(this.consoleColor, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return null;
        }
    }

    class MyCallContextInitializer : ICallContextInitializer
    {
        public void AfterInvoke(object correlationState)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }

        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return null;
        }
    }

    class MyOperationInvoker : IOperationInvoker
    {
        IOperationInvoker inner;
        public MyOperationInvoker(IOperationInvoker inner)
        {
            this.inner = inner;
        }

        public object[] AllocateInputs()
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.AllocateInputs();
        }

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.Invoke(instance, inputs, out outputs);
        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.InvokeBegin(instance, inputs, callback, state);
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.InvokeEnd(instance, out outputs, result);
        }

        public bool IsSynchronous
        {
            get
            {
                ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
                return this.inner.IsSynchronous;
            }
        }
    }

    class MyInstanceProvider : IInstanceProvider
    {
        Type serviceType;
        public MyInstanceProvider(Type serviceType)
        {
            this.serviceType = serviceType;
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return Activator.CreateInstance(this.serviceType);
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return Activator.CreateInstance(this.serviceType);
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }
    }

    class MyInstanceContextProvider : IInstanceContextProvider
    {
        IInstanceContextProvider inner;
        public MyInstanceContextProvider(IInstanceContextProvider inner)
        {
            this.inner = inner;
        }

        public InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.GetExistingInstanceContext(message, channel);
        }

        public void InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            this.inner.InitializeInstanceContext(instanceContext, message, channel);
        }

        public bool IsIdle(InstanceContext instanceContext)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return this.inner.IsIdle(instanceContext);
        }

        public void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            this.inner.NotifyIdle(callback, instanceContext);
        }
    }

    class MyInstanceContextInitializer : IInstanceContextInitializer
    {
        public void Initialize(InstanceContext instanceContext, Message message)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }
    }

    class MyChannelInitializer : IChannelInitializer
    {
        ConsoleColor consoleColor;
        public MyChannelInitializer(bool isServer)
        {
            this.consoleColor = isServer ? ConsoleColor.Cyan : ConsoleColor.Yellow;
        }
        public void Initialize(IClientChannel channel)
        {
            ColorConsole.WriteLine(this.consoleColor, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }
    }

    class MyClientOperationSelector : IClientOperationSelector
    {
        public bool AreParametersRequiredForSelection
        {
            get
            {
                ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
                return false;
            }
        }

        public string SelectOperation(MethodBase method, object[] parameters)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return method.Name;
        }
    }

    class MyInteractiveChannelInitializer : IInteractiveChannelInitializer
    {
        public IAsyncResult BeginDisplayInitializationUI(IClientChannel channel, AsyncCallback callback, object state)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            Action act = new Action(this.DoNothing);
            return act.BeginInvoke(callback, state);
        }

        public void EndDisplayInitializationUI(IAsyncResult result)
        {
            ColorConsole.WriteLine(ConsoleColor.Yellow, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
        }

        private void DoNothing() { }
    }

    class MyErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            return error is ArgumentException;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            ColorConsole.WriteLine(ConsoleColor.Cyan, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));
            MessageFault messageFault = MessageFault.CreateFault(new FaultCode("FaultCode"), new FaultReason(error.Message));
            fault = Message.CreateMessage(version, messageFault, "FaultAction");
        }
    }

    public class MyAuthorizationPolicy : IAuthorizationPolicy
    {
        string id;
        public MyAuthorizationPolicy()
        {
            id = Guid.NewGuid().ToString();
        }

        public bool Evaluate(EvaluationContext evaluationContext, ref object state)
        {
            ColorConsole.WriteLine(ConsoleColor.Green, "{0}.{1}", this.GetType().Name, ReflectionUtil.GetMethodSignature(MethodBase.GetCurrentMethod()));

            if (OperationContext.Current.InstanceContext != null)
            {
                var instance = (Service)OperationContext.Current.InstanceContext.GetServiceInstance();
                ColorConsole.WriteLine(ConsoleColor.Green, "Got the service instance. Name={0}", instance.Name);
            }
            else
            {
                ColorConsole.WriteLine(ConsoleColor.Green, "OperationContext.Current.InstanceContext is null");
            }

            // Return true, indicating that this method does not need to be called again.
            return true;
        }

        public ClaimSet Issuer
        {
            get { return ClaimSet.System; }
        }

        public string Id
        {
            get { return id; }
        }
    }

    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        int Add(int x, int y);
        [OperationContract(IsOneWay = true)]
        void Process(string text);
    }

    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class Service : ITest
    {
        public Service() { ColorConsole.WriteLine(ConsoleColor.Green, "Created Service Instance"); }

        public string Name { get { return "MyService instance 1234"; } }

        public int Add(int x, int y)
        {
            ColorConsole.WriteLine(ConsoleColor.Green, "In service operation '{0}'", MethodBase.GetCurrentMethod().Name);

            if (x == 0 && y == 0)
            {
                throw new ArgumentException("This will cause IErrorHandler to be called");
            }
            else
            {
                return x + y;
            }
        }

        public void Process(string text)
        {
            ColorConsole.WriteLine(ConsoleColor.Green, "In service operation '{0}'", MethodBase.GetCurrentMethod().Name);
        }
    }

    class MyBehavior : IOperationBehavior, IContractBehavior
    {
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            clientOperation.Formatter = new MyClientMessageFormatter(clientOperation.Formatter);
            clientOperation.ParameterInspectors.Add(new MyParameterInspector(false));
        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.CallContextInitializers.Add(new MyCallContextInitializer());
            dispatchOperation.Formatter = new MyDispatchMessageFormatter(dispatchOperation.Formatter);
            dispatchOperation.Invoker = new MyOperationInvoker(dispatchOperation.Invoker);
            dispatchOperation.ParameterInspectors.Add(new MyParameterInspector(true));
        }

        public void Validate(OperationDescription operationDescription)
        {
        }

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ChannelInitializers.Add(new MyChannelInitializer(false));
            clientRuntime.InteractiveChannelInitializers.Add(new MyInteractiveChannelInitializer());
            clientRuntime.MessageInspectors.Add(new MyClientMessageInspector());
            clientRuntime.OperationSelector = new MyClientOperationSelector();
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.ChannelDispatcher.ChannelInitializers.Add(new MyChannelInitializer(true));
            dispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(new MyErrorHandler());
            dispatchRuntime.InstanceContextInitializers.Add(new MyInstanceContextInitializer());
            dispatchRuntime.InstanceContextProvider = new MyInstanceContextProvider(dispatchRuntime.InstanceContextProvider);
            dispatchRuntime.InstanceProvider = new MyInstanceProvider(dispatchRuntime.ChannelDispatcher.Host.Description.ServiceType);
            dispatchRuntime.MessageInspectors.Add(new MyDispatchMessageInspector());
            dispatchRuntime.OperationSelector = new MyDispatchOperationSelector();
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
        }
    }

    static class ColorConsole
    {
        static object syncRoot = new object();

        public static void WriteLine(ConsoleColor color, string text, params object[] args)
        {
            if (args != null && args.Length > 0)
            {
                text = string.Format(CultureInfo.InvariantCulture, text, args);
            }

            lock (syncRoot)
            {
                Console.ForegroundColor = color;
                Console.WriteLine("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), text);
                Console.ResetColor();
            }

            Thread.Sleep(50);
        }

        public static void WriteLine(string text, params object[] args)
        {
            Console.WriteLine(text, args);
        }

        public static void WriteLine(object obj)
        {
            Console.WriteLine(obj);
        }
    }

    static class ReflectionUtil
    {
        public static string GetMethodSignature(MethodBase method)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(method.Name);
            sb.Append("(");
            ParameterInfo[] parameters = method.GetParameters();
            for (int i = 0; i < parameters.Length; i++)
            {
                if (i > 0) sb.Append(", ");
                sb.Append(parameters[i].ParameterType.Name);
            }
            sb.Append(")");
            return sb.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            using (ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)))
            {
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
                endpoint.Contract.Behaviors.Add(new MyBehavior());
                foreach (OperationDescription operation in endpoint.Contract.Operations)
                {
                    operation.Behaviors.Add(new MyBehavior());
                }

                var polices = new List<IAuthorizationPolicy>();
                polices.Add(new MyAuthorizationPolicy());
                host.Authorization.ExternalAuthorizationPolicies = polices.AsReadOnly();

                host.Open();
                ColorConsole.WriteLine("Host opened");

                using (ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress)))
                {
                    factory.Endpoint.Contract.Behaviors.Add(new MyBehavior());
                    foreach (OperationDescription operation in factory.Endpoint.Contract.Operations)
                    {
                        operation.Behaviors.Add(new MyBehavior());
                    }

                    ITest proxy = factory.CreateChannel();
                    ColorConsole.WriteLine("Calling operation");
                    ColorConsole.WriteLine(proxy.Add(3, 4));

                    //ColorConsole.WriteLine("Called operation, calling it again, this time it the service will throw");
                    //try
                    //{
                    //    ColorConsole.WriteLine(proxy.Add(0, 0));
                    //}
                    //catch (Exception e)
                    //{
                    //    ColorConsole.WriteLine(ConsoleColor.Red, "{0}: {1}", e.GetType().Name, e.Message);
                    //}

                    //ColorConsole.WriteLine("Now calling an OneWay operation");
                    //proxy.Process("hello");

                    ((IClientChannel)proxy).Close();
                }
            }

            ColorConsole.WriteLine("Done");
        }
    }
}

程序输出

寻找 ---->。

[12:33:04.218] MyOperationInvoker.get_IsSynchronous()
[12:33:04.269] MyOperationInvoker.get_IsSynchronous()
Host opened
[12:33:04.322] MyChannelInitializer.Initialize(IClientChannel)
Calling operation
[12:33:04.373] MyClientOperationSelector.get_AreParametersRequiredForSelection()
[12:33:04.424] MyClientOperationSelector.SelectOperation(MethodBase, Object[])
[12:33:04.474] MyParameterInspector.BeforeCall(String, Object[])
[12:33:04.524] MyClientMessageFormatter.SerializeRequest(MessageVersion, Object[])
[12:33:04.574] MyClientMessageInspector.BeforeSendRequest(Message&, IClientChannel)
[12:33:04.632] MyInteractiveChannelInitializer.BeginDisplayInitializationUI(IClientChannel, AsyncCallback, Object)
[12:33:04.684] MyInteractiveChannelInitializer.EndDisplayInitializationUI(IAsyncResult)
[12:33:04.788] MyChannelInitializer.Initialize(IClientChannel)
[12:33:04.838] MyInstanceContextProvider.GetExistingInstanceContext(Message, IContextChannel)
[12:33:04.888] MyDispatchOperationSelector.SelectOperation(Message&)
[12:33:04.939] MyInstanceContextProvider.InitializeInstanceContext(InstanceContext, Message, IContextChannel)
[12:33:04.990] MyInstanceContextInitializer.Initialize(InstanceContext, Message)
[12:33:05.040] MyDispatchMessageInspector.AfterReceiveRequest(Message&, IClientChannel, InstanceContext)
[12:33:05.091] MyInstanceProvider.GetInstance(InstanceContext, Message)
[12:33:05.142] Created Service Instance
[12:33:05.192] MyCallContextInitializer.BeforeInvoke(InstanceContext, IClientChannel, Message)
[12:33:05.242] MyOperationInvoker.AllocateInputs()
[12:33:05.293] MyDispatchMessageFormatter.DeserializeRequest(Message, Object[])
[12:33:05.344] MyParameterInspector.BeforeCall(String, Object[])
[12:33:05.394] MyAuthorizationPolicy.Evaluate(EvaluationContext, Object&)
---->[12:33:05.445] Got the service instance. Name=MyService instance 1234
[12:33:05.495] MyOperationInvoker.Invoke(Object, Object[], Object[]&)
[12:33:05.547] In service operation 'Add'
[12:33:05.597] MyParameterInspector.AfterCall(String, Object[], Object, Object)
[12:33:05.648] MyDispatchMessageFormatter.SerializeReply(MessageVersion, Object[], Object)
[12:33:05.698] MyCallContextInitializer.AfterInvoke(Object)
[12:33:05.748] MyDispatchMessageInspector.BeforeSendReply(Message&, Object)
[12:33:05.803] MyInstanceContextProvider.IsIdle(InstanceContext)
[12:33:05.804] MyClientMessageInspector.AfterReceiveReply(Message&, Object)
[12:33:05.854] MyInstanceProvider.ReleaseInstance(InstanceContext, Object)
[12:33:05.855] MyClientMessageFormatter.DeserializeReply(Message, Object[])
[12:33:05.905] MyParameterInspector.AfterCall(String, Object[], Object, Object)

1
这相当令人印象深刻。没有自定义实例提供程序,它还能正常工作吗? - user585968
它不会将策略严密地耦合到服务中,因为我想要检查的只是该服务是否实现了一个组件中定义并被我们组织中几乎所有代码使用的接口。特定的服务对策略并不重要。此外,回应Micky的问题 - 有没有一种方法可以在不替换所有内容的情况下获得它?这是一个托管在IIS上的服务。 - zimdanen
如果只使用IAuthorizationPolicy,它可以正常工作。行为、实例提供程序等仅用于解决执行顺序的评论以及服务实例是否已创建的问题。要进行测试,请从Main()方法中注释掉与MyBehavior有关的任何内容。 - ErnieL
在 IIS 中托管时是否有获取服务的方法? - zimdanen

1

IAuthorizationPolicy 实现 evaluate 方法,进而提供上下文。

来自 Microsoft。

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
    bool bRet = false;
    CustomAuthState customstate = null;

    // If state is null, then this method has not been called before, so  
    // set up a custom state. 
    if (state == null)
    {
        customstate = new CustomAuthState();
        state = customstate;
    }
    else
        customstate = (CustomAuthState)state;

    Console.WriteLine("Inside MyAuthorizationPolicy::Evaluate");

    // If claims have not been added yet... 
    if (!customstate.ClaimsAdded)
    {
        // Create an empty list of Claims.
        IList<Claim> claims = new List<Claim>();

        // Iterate through each of the claim sets in the evaluation context. 
        foreach (ClaimSet cs in evaluationContext.ClaimSets)
            // Look for Name claims in the current claim set. 
            foreach (Claim c in cs.FindClaims(ClaimTypes.Name, Rights.PossessProperty))
                // Get the list of operations the given username is allowed to call. 
                foreach (string s in GetAllowedOpList(c.Resource.ToString()))
                {
                    // Add claims to the list.
                    claims.Add(new Claim("http://example.org/claims/allowedoperation", s, Rights.PossessProperty));
                    Console.WriteLine("Claim added {0}", s);
                }

        // Add claims to the evaluation context.
        evaluationContext.AddClaimSet(this, new DefaultClaimSet(this.Issuer,claims));

        // Record that claims have been added.
        customstate.ClaimsAdded = true;

        // Return true, which indicates this need not be called again.
        bRet = true;
    }
    else
    {
        // This point should not be reached, but just in case...
        bRet = true;
    }


    return bRet;
}

例如,查看 http://msdn.microsoft.com/en-us/library/ms729794(v=vs.110).aspx

使用反射获取当前程序集的名称

Assembly SampleAssembly;
// Instantiate a target object.
Int32 Integer1 = new Int32();
Type Type1;
// Set the Type instance to the target class type.
Type1 = Integer1.GetType();
// Instantiate an Assembly class to the assembly housing the Integer type.  
SampleAssembly = Assembly.GetAssembly(Integer1.GetType());
// Display the name of the assembly currently executing
Console.WriteLine("GetExecutingAssembly=" + Assembly.GetExecutingAssembly().FullName);

此上下文涉及安全上下文,它不会直接调用,考虑将其作为服务方法的属性: [PrincipalPermission(SecurityAction.Demand, Role = "ADMIN")] public void TheMethod() 并且自定义接口与服务绑定,在service.config文件中使用自定义行为。 { ... } - Mike Beeler
嗯,我可以获取通道、请求上下文和其他东西;只是似乎缺少实例上下文。你是说没有办法访问正在进行授权的服务吗? - zimdanen
1
真的吗?OP不想使用属性来传递服务名称,反射是另一种方法,如果您有更好的想法,请贡献出来。 - Mike Beeler
1
@MikeBeeler 不正确。你的“答案”只是 IAuthorizationPolicy 的一个实现而已。“传递服务名称” - OP 在哪里明确表示他希望得到这个信息? - user585968
1
这更多是一个上下文传递问题,而不是一个授权日志记录问题。 - zimdanen
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接