Asp.net 使用FormsAuthentication以编程方式测试对给定路径的访问

Asp.net 使用FormsAuthentication以编程方式测试对给定路径的访问,asp.net,forms-authentication,Asp.net,Forms Authentication,是否可以通过编程测试当前用户是否能够访问给定路径?这将是我需要限制访问的某个资源的路径,它将是通过处理程序而不是直接通过其路径访问的资源 例如,给定这些配置设置: <authentication mode="Forms"> <forms loginUrl="~/login/" defaultUrl="~/private/" protection="All" cookieless="UseCookies" slidingExpiration="true" path="/" /

是否可以通过编程测试当前用户是否能够访问给定路径?这将是我需要限制访问的某个资源的路径,它将是通过处理程序而不是直接通过其路径访问的资源

例如,给定这些配置设置:

<authentication mode="Forms">
  <forms loginUrl="~/login/" defaultUrl="~/private/" protection="All" cookieless="UseCookies" slidingExpiration="true" path="/" />
</authentication>

...

<location path="private">
  <system.web>
    <authorization>
      <deny users="?" />
      <allow users="*" />
    </authorization>
  </system.web>
</location>
<location path="private/general">
  <system.web>
    <authorization>
      <allow roles="general" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>
对于“常规”角色中的用户,哪个将返回
true
;对于其他任何用户,哪个将返回
false


请注意,配置设置只是一个示例—可能会有更多的位置定义和角色等,因此使用大量的
myPath.StartsWith(“/private/”)
语句进行测试并不是一个好的解决方案。

我从未完全弄清楚这一点,因此我不得不稍微改变方法

这是假设我们试图获取的资源是IIS通常不会提供的资源——在我的例子中,这是web表单用户控件(.ascx),我希望通过Ajax获取该控件,并将其呈现为字符串,然后通过JavaScript将其注入HTML中的某个位置

我去掉了处理程序,改为直接向资源发出对这些资源的任何请求,但扩展名稍微修改了.ascx.asmx。例如,
/private/general/my resource.ascx.asmx

然后,我添加了一个HTTP模块(集成管道模式):

此模块将请求的URL重写为一个web服务(MyResource.asmx),然后去掉我们最初添加的额外扩展名,最后为我们试图访问的文件提供服务(在本例中,是一个web表单用户控件):

(使用此RenderToString扩展方法):

这一切都是有效的,因为表单身份验证在允许请求之前通过web.config中设置的授权规则运行,因此我们知道,当它到达HTTP模块时,可以为请求的文件提供服务,因为当前用户必须具有访问路径的权限

HttpContext.Current.User.Identity.IsAllowedToAccess("~/private/general/my-resource")
<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="MyResourceHttpModule" type="MyApp.Controls.MyResourceHttpModule" />
  </modules>
</system.webServer>
<system.web>
  <httpModules>
    <add name="MyResourceHttpModule" type="MyApp.Controls.MyResourceHttpModule" />
  </httpModules>
</system.web>
using System;
using System.Web;

namespace MyApp.Controls
{
    public class MyResourceHttpModule : IHttpModule
    {
        #region IHttpModule Members

        public void Dispose()
        {
        }

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

        #endregion

        void OnAuthorizeRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;

            if (application.Context.Request.Url.AbsolutePath.EndsWith(".ascx.asmx"))
            {
                application.Context.RewritePath("~/Services/MyResource.asmx/GetResource");
            }
        }
    }
}
using System.Collections.Generic;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.UI;

namespace MyApp.Services
{
    [ScriptService]
    public class MyResource : System.Web.Services.WebService
    {
        [WebMethod(EnableSession = true)]
        public object GetResource()
        {
            var controlPath = HttpContext.Current.Request.RawUrl;

            if (Paths.ApplicationPath != "" && controlPath.StartsWith(Paths.ApplicationPath)) controlPath = '~' + controlPath.Substring(Paths.ApplicationPath.Length);
            if (controlPath.EndsWith(".asmx")) controlPath = controlPath.Substring(0, controlPath.Length - 5);

            using (var myUserControl = (MyApp.Controls.MyUserControl)(new Page()).LoadControl(controlPath))
            {
                myUserControl.DataBind();

                return myUserControl.RenderToString();
            }
        }
    }
}
public static string RenderToString(this System.Web.UI.Control control)
{
    var stringBuilder = new StringBuilder();

    using (var stringWriter = new StringWriter(stringBuilder))
    {
        using (var htmlTextWriter = new System.Web.UI.HtmlTextWriter(stringWriter))
        {
            control.RenderControl(htmlTextWriter);

            return stringBuilder.ToString();
        }
    }
}