【问题标题】:Setting up authorization and a "Access-denied" page设置授权和“拒绝访问”页面
【发布时间】:2017-02-03 17:30:46
【问题描述】:

我正在开发一个 ASP.Net MVC 应用程序。我想拒绝所有未经身份验证或不在 AD 组中的用户访问。只有这个 AD 组应该有访问权限。例外是“你不能通过!”页。任何人都可以访问它。

在项目根目录中,我的 web.config 中有这个(为简洁起见,对文件的其余部分进行了修剪):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <customErrors mode="On">
            <error statusCode="401" redirect="/ui/Other/YouShallNotPass.html" />
        </customErrors>
        <compilation debug="true" targetFramework="4.5.2" />
        <httpRuntime targetFramework="4.5.2" />
        <authentication mode="Windows" />
        <authorization>
            <allow roles="allowedrole"/>
            <deny users="*"/>
        </authorization>
    </system.web>
    <system.webServer>
        <httpErrors>
            <remove statusCode="401" />
            <error statusCode="401" 
                   subStatusCode="2" 
                   responseMode="ExecuteURL" 
                   path="/ui/Other/YouShallNotPass.html" />
        </httpErrors>
    </system.webServer>
</configuration>

我在ui/Other/YouShallNotPass.html 旁边还有第二个 web.config。我希望这允许任何人访问此页面,无论是否经过身份验证:

<configuration>
    <system.web>
        <authorization>
            <allow users="?"/>
        </authorization>
    </system.web>
</configuration>

我可以通过将 AD 组设置为不存在的组来测试这一点。我不属于不存在的组,所以我应该期待看到YouShallNotPass.html 页面。

它没有按预期工作。我的浏览器出现以下错误:

错误消息 401.2.:未经授权:由于服务器配置,登录失败。根据您提供的凭据和 Web 服务器上启用的身份验证方法,验证您是否有权查看此目录或页面。

如果我直接请求YouShallNotPass.html,我可以在提示输入用户/密码后访问它。

我做错了什么?用户未授权时为什么不提供401页面?

【问题讨论】:

  • 尝试在您的YouShallNotPass.html 的web.config 中插入&lt;authentication mode="None" /&gt;,看看会发生什么。由于浏览器仍在提示用户/通过,这意味着该页面仍需要 Windows 身份验证(因为您将其放在主 web.config 中并且没有覆盖它)。
  • 当我直接请求YouShallNotPass.html 时,它不再要求用户/通行证。但任何其他页面,我仍然得到原来的错误。
  • 您的访问池用户是否可能无权访问您正在对其进行身份验证的数据库?
  • 身份验证工作正常,我没有针对数据库进行身份验证。

标签: c# asp.net asp.net-mvc web-config authorization


【解决方案1】:

查看此question,因为它解释了为什么您的解决方案不起作用。

因此,一旦您使用 [Authorize] 对所有安全控制器操作进行注释,您就可以添加自定义 ExceptionFilter

喜欢这个

public class HandleUnauthorizedAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if (filterContext.Exception.GetType() != typeof (SecurityException)) return;

        var controllerName = (string) filterContext.RouteData.Values["controller"];
        var actionName = (string) filterContext.RouteData.Values["action"];
        var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

        filterContext.Result = new ViewResult
        {
            ViewName = "Unauthorized",
            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = 403;
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

然后在这里接线

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleUnauthorizedAttribute());
    }
}

【讨论】:

  • 这适用于我的情况吗? YouShallNotPass.html 是一个静态 HTML 文件。它不是由控制器提供的。
  • 关键是您不能在 web.config 中配置安全性,您可以在其中锁定整个站点,然后像使用 asp.net webforms 一样使用 打开漏洞.所以 1. 在您的控制器操作上使用 authorize 属性 2. 在您执行 1 之后您可能可以使用他的自定义错误,因为您没有锁定所有内容。
  • 另一个问题是您在这里将身份验证(您是谁)与授权(您可以做什么)混合在一起。身份验证错误是 401。授权错误是 403。
  • 我也会更改为视图,就像我的解决方案一样,因为您可以在错误页面上看到其他信息,例如他们试图访问的内容。
  • 我对将其更改为视图不感兴趣。 1) 我已经在使用 [Authorize],2) 我的自定义错误部分不起作用,3) 我正在锁定所有内容,包括静态文件,而使用 Authorize 无法完成。
【解决方案2】:

通过将以下内容添加到我的 global.asax 来解决此问题:

protected void Application_EndRequest(object sender, EventArgs e)
{
    if (Response.StatusCode != 401)
        return;

    Response.ClearContent();
    Response.WriteFile("~/ui/Other/YouShallNotPass.html");
    Response.ContentType = "text/html";
}

不过,我更愿意使用 web.config 来执行此操作。

【讨论】:

  • 您是否尝试在主 web.config 中使用 &lt;location&gt; 元素而不是第二个 web.config?这可能比必须拦截响应更清洁。
  • 是的,我做到了。不过,我不记得为什么它现在不起作用了。
猜你喜欢
  • 1970-01-01
  • 2016-03-16
  • 2020-04-26
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多