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