Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 从HTTP模块获取ASMX Web服务的自定义属性_Asp.net_Asmx_Httpmodule - Fatal编程技术网

Asp.net 从HTTP模块获取ASMX Web服务的自定义属性

Asp.net 从HTTP模块获取ASMX Web服务的自定义属性,asp.net,asmx,httpmodule,Asp.net,Asmx,Httpmodule,情况如下: 旧版ASP.NET产品。许多旧的ASMX服务(在其他类型的端点中——ASPX、ASHX等) 我们正在增强一些安全逻辑。部分更改要求定义每个ASMX服务所属的应用程序模块。为此,我们计划使用如下所示的自定义属性 [AttributeUsage(AttributeTargets.Class)] public class ModuleAssignmentAttribute : Attribute { public Module[] Modules { get; set; }

情况如下:

旧版ASP.NET产品。许多旧的ASMX服务(在其他类型的端点中——ASPX、ASHX等)

我们正在增强一些安全逻辑。部分更改要求定义每个ASMX服务所属的应用程序模块。为此,我们计划使用如下所示的自定义属性

[AttributeUsage(AttributeTargets.Class)]
public class ModuleAssignmentAttribute : Attribute
{
    public Module[] Modules { get; set; }

    public ModuleAssignmentAttribute(params Module[] modules)
    {
        Modules = modules;
    }
}
下面是如何将模块应用于ASMX服务的示例

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ModuleAssignment(Module.ApplicationModuleA)]
public class SomeService : System.Web.Services.WebService
{
    [WebMethod(true)]
    public string GetValue()
    {
        return "Some Service Value";
    }
}
下面的HTTP模块将用于授权访问该服务

公共类MyAuthorizationModule:IHttpModule { 公共空间处置() { //这里有清理代码。 }

    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += new EventHandler(OnAuthorizeRequest);
    }

    public void OnAuthorizeRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Handler == null) return;

        Attribute att = Attribute.GetCustomAttribute(HttpContext.Current.Handler.GetType(), typeof(ModuleAssignmentAttribute));

        if (att != null)
        {
            Module[] modules = ((ModuleAssignmentAttribute)att).Modules;

            // Simulate getting the user's active role ID
            int roleId = 1;

            // Simulate performing an authz check
            AuthorizationAgent agent = new AuthorizationAgent();
            bool authorized = agent.AuthorizeRequest(roleId, modules);
            if (!authorized)
            {
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.StatusCode = 401;
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }
    }
问题是,对于ASMXWeb服务,HTTP模块中的以下代码行返回null(请注意,这适用于ASPX页面)

在这种情况下,HttpContext.Current.Handler.GetType()的值是“System.Web.Script.Services.ScriptHandlerFactory+HandlerWrapperWithSession”。该类型显然不知道在ASMX服务上定义的自定义属性

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ModuleAssignment(Module.ApplicationModuleA)]
public class SomeService : System.Web.Services.WebService
{
    [WebMethod(true)]
    public string GetValue()
    {
        return "Some Service Value";
    }
}

关于如何在此场景中从ASMX服务类型获取自定义属性,您有什么想法吗?

这里有一个问题的解决方案。需要反思。丑陋而脆弱的代码-如果不需要,我不建议您使用它。我想知道我是否忽略了更优雅的方式

    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += new EventHandler(OnAuthorizeRequest);
    }

    public void OnAuthorizeRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Handler == null) return;

        Attribute att = null;

        // ScriptHandlerFactory+HandlerWrapperWithSession is the type of handler for ASMX web service calls to web methods that use session.
        // This class is internal, so need to do a string comparison here (is there another way?).
        if (HttpContext.Current.Handler.GetType().ToString() == "System.Web.Script.Services.ScriptHandlerFactory+HandlerWrapperWithSession")
        {
            // HandlerWrapperWithSession has a protected field named "_originalHandler" that it inherits from HandlerWrapper.
            FieldInfo originalHandlerField = HttpContext.Current.Handler.GetType().GetField("_originalHandler",BindingFlags.NonPublic | BindingFlags.Instance);
            object originalHandler = originalHandlerField.GetValue(HttpContext.Current.Handler);

            // The _originalHandler value is an instance of SyncSessionHandler.
            // The inheritance tree for SyncSessionHandler is:
            //
            //    WebServiceHandler
            //    ----> SyncSessionlessHandler
            //          ----> SyncSessionHandler
            //
            // We need to walk the tree up to the WebServiceHandler class.
            bool exitLoop = false;
            Type t = originalHandler.GetType();
            while (t != null)
            {
                // WebServiceHandler is internal, so again another string comparison.
                if (t.ToString() == "System.Web.Services.Protocols.WebServiceHandler")
                {
                    // WebServiceHandler has a private field named protocol.  This field has the type HttpGetServerProtocol.
                    FieldInfo protocolField = t.GetField("protocol", BindingFlags.NonPublic | BindingFlags.Instance);
                    object protocolValue = protocolField.GetValue(originalHandler);

                    // The inheritance tree for ServerProtocol is:
                    //
                    //    HttpServerProtocol
                    //    ----> HttpGetServerProtocol
                    //
                    // We need to walk the three up to the HttpServerProtocol class.
                    Type t2 = protocolValue.GetType();
                    while (t2 != null)
                    {
                        if (t2.ToString() == "System.Web.Services.Protocols.HttpServerProtocol")
                        {
                            // HttpServerProtocol has an internal property named MethodInfo.  This property has the type LogicalMethodInfo.
                            PropertyInfo methodInfoProperty = t2.GetProperty("MethodInfo", BindingFlags.NonPublic | BindingFlags.Instance);
                            object methodInfoValue = methodInfoProperty.GetValue(protocolValue);

                            // The LogicalMethodInfo class has a DeclaringType property.  This property stores the type of the ASMX service. 
                            att = Attribute.GetCustomAttribute(((LogicalMethodInfo)methodInfoValue).DeclaringType, typeof(ModuleAssignmentAttribute));
                            exitLoop = true;
                            break;
                        }

                        t2 = t2.BaseType;
                    }
                }

                if (exitLoop) break;
                t = t.BaseType;
            }
        }
        else
        {
            att = Attribute.GetCustomAttribute(HttpContext.Current.Handler.GetType(), typeof(ModuleAssignmentAttribute));
        }

        if (att != null)
        {
            Module[] modules = ((ModuleAssignmentAttribute)att).Modules;

            // Simulate getting the user's active role ID
            int roleId = 1;

            // Simulate performing an authz check
            AuthorizationAgent agent = new AuthorizationAgent();
            bool authorized = agent.AuthorizeRequest(roleId, modules);
            if (!authorized)
            {
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.StatusCode = 401;
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }
    }

我必须使用Reflector+运行时调试来找到这个解决方案。

HttpContext.Current.Handler.GetType()的值是多少?@Mason-System.Web.Script.Services.ScriptHandlerFactory+HandlerWrapperWithSession我想这是你的问题。处理程序不是你期望的
SomeService
类。它正在检索的类没有该属性。不幸的是,我不知道是否有可靠的方法从该上下文中获取ASMX类。你知道吗可能可以通过检查URL或路由来实现。如果可以的话,将所有ASMX转换为ASHX可能会更容易。@Mason-不幸的是,这不是一个可行的解决方案。有70多个服务/1000多个web方法。你有路由吗?或者是像
~/SomeService.ASMX/GetValue
这样的简单URL吗?你可能可以使用URL来确定ich服务类实例化并从中获取属性。