WebForms 身份验证作为 MVC 过滤器
WebForms authentication as MVC filter
在从 WebForms 到 MVC 的迁移过程中,保留了一些 .aspx 页面。这些认证目前是基于文件的,并通过 Web.config 进行。 MVC 身份验证通过将 AuthorizeAttribute
添加到 GlobalFilters.Filters
并根据需要添加到 controllers/actions 来实现。
Web.config 身份验证当前如下所示:
<authentication mode="Forms">
<forms loginUrl="~/SignIn.aspx" protection="All" path="/" timeout="10080" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<location path="SomePage.aspx">
<system.web>
<authorization>
<allow roles="Administrator, BasicUser" />
<deny users="*" />
</authorization>
</system.web>
</location>
不过,我想将 WebForms 身份验证从 Web.config 移到使用方法调用执行检查的 MVC 过滤器中。我找不到一个这样的例子。这甚至可能吗,这样做是否有任何不良影响?
我知道默认情况下 MVC 挂钩不处理 .aspx 文件。
我正在寻找一种获取所有 .aspx 文件的方法,无论它们的代码隐藏基础 class 是什么。
在Global.asax.cs、
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// Since MVC does not handle authentication for .aspx pages, do this here.
AuthController.AuthenticateAspxPage(this.Context);
}
在 AuthController 中,对于某些类型 UserRole
,
public const string ErrorRedirectUrl = "~/Auth/Error";
private static readonly IDictionary<string, UserRole[]> _aspxAccessRoles =
new Dictionary<string, UserRole[]>()
{
{ "~/SomePage.aspx", new UserRole[] { UserRole.Administrator,
UserRole.BasicUser } },
...
};
然后,
[NonAction]
public static void AuthenticateAspxPage(HttpContext context)
{
string ext = context.Request.CurrentExecutionFilePathExtension;
string aspxPage = context.Request.AppRelativeCurrentExecutionFilePath;
ClaimsPrincipal principal = context.User as ClaimsPrincipal;
if ((ext == ".aspx" || ext == ".ashx") && !HasAspxAccess(aspxPage, principal))
{
context.Response.Redirect(ErrorRedirectUrl);
}
}
[NonAction]
public static bool HasAspxAccess(string aspxPage, ClaimsPrincipal principal)
{
if (principal == null || principal.Claims == null)
{
return false;
}
string[] userRoles = principal.Claims
.Where(claim => claim.Type == ClaimTypes.Role)
.Select(claim => claim.Value)
.ToArray();
UserRole[] accessRoles;
return _aspxAccessRoles.TryGetValue(aspxPage, out accessRoles)
&& accessRoles.Any(role => userRoles.Contains(role.ToString()));
}
在从 WebForms 到 MVC 的迁移过程中,保留了一些 .aspx 页面。这些认证目前是基于文件的,并通过 Web.config 进行。 MVC 身份验证通过将 AuthorizeAttribute
添加到 GlobalFilters.Filters
并根据需要添加到 controllers/actions 来实现。
Web.config 身份验证当前如下所示:
<authentication mode="Forms">
<forms loginUrl="~/SignIn.aspx" protection="All" path="/" timeout="10080" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<location path="SomePage.aspx">
<system.web>
<authorization>
<allow roles="Administrator, BasicUser" />
<deny users="*" />
</authorization>
</system.web>
</location>
不过,我想将 WebForms 身份验证从 Web.config 移到使用方法调用执行检查的 MVC 过滤器中。我找不到一个这样的例子。这甚至可能吗,这样做是否有任何不良影响?
我知道默认情况下 MVC 挂钩不处理 .aspx 文件。
我正在寻找一种获取所有 .aspx 文件的方法,无论它们的代码隐藏基础 class 是什么。
在Global.asax.cs、
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// Since MVC does not handle authentication for .aspx pages, do this here.
AuthController.AuthenticateAspxPage(this.Context);
}
在 AuthController 中,对于某些类型 UserRole
,
public const string ErrorRedirectUrl = "~/Auth/Error";
private static readonly IDictionary<string, UserRole[]> _aspxAccessRoles =
new Dictionary<string, UserRole[]>()
{
{ "~/SomePage.aspx", new UserRole[] { UserRole.Administrator,
UserRole.BasicUser } },
...
};
然后,
[NonAction]
public static void AuthenticateAspxPage(HttpContext context)
{
string ext = context.Request.CurrentExecutionFilePathExtension;
string aspxPage = context.Request.AppRelativeCurrentExecutionFilePath;
ClaimsPrincipal principal = context.User as ClaimsPrincipal;
if ((ext == ".aspx" || ext == ".ashx") && !HasAspxAccess(aspxPage, principal))
{
context.Response.Redirect(ErrorRedirectUrl);
}
}
[NonAction]
public static bool HasAspxAccess(string aspxPage, ClaimsPrincipal principal)
{
if (principal == null || principal.Claims == null)
{
return false;
}
string[] userRoles = principal.Claims
.Where(claim => claim.Type == ClaimTypes.Role)
.Select(claim => claim.Value)
.ToArray();
UserRole[] accessRoles;
return _aspxAccessRoles.TryGetValue(aspxPage, out accessRoles)
&& accessRoles.Any(role => userRoles.Contains(role.ToString()));
}