当使用 ADFS 和 ASP.NET MVC 时 s/he 未被授权时将用户重定向到自定义页面

Redirect user to custom page when s/he is not authorized when using ADFS and ASP.NET MVC

我的 ADFS 配置排除了所有不属于一组组的用户。

在某些情况下,用户使用 ADFS 登录 Web 应用程序(Web 应用程序 B)并获得一组不包含 Web 应用程序 A 中接受的任何组的声明。

然后用户转到网络应用程序 A,被重定向到 ADFS,用户已经有 ADFS 的 cookie,因此不会要求他提供新的 user/password 组合,他会立即使用相同的重定向对网络应用程序 A 的声明(网络应用程序 B 的声明)。

这将在网络应用 A 中触发 401,这是正确的。

我们如何将用户重定向到解释刚刚发生的事情的页面(使用 "login with a different account" 按钮)?

作为参考,排除不属于一组组的所有用户的 web.config 配置是:

<authentication mode="None" />
<authorization>
  <allow roles="GroupA,GroupB,GroupC,GroupD"/>
  <deny users="*" />
</authorization>

指定要重定向到 401 的页面:

<customErrors mode="On">
    <error code="401" path="401.cshtml" />
</customErrors>

在 401 页面中进行授权。

如果有人必须处理这个问题,这就是我显示自定义未经授权页面的方式。

创建一个自定义的未经授权的页面,也许在那里放一个注销按钮,我把我的放在 ErrorController 中并将操作命名为 Unauthorized。

首先 "white-list" web.config

中的自定义 "you are not authorized" 页面
<location path="Error/Unauthorized">
    <system.web>
        <authorization>
            <allow Users="*"/>
        </authorization>
    </system.web>
</location>

注意:如果您使用 resharper,它会突出显示路径 "Error/Unauthorized" 不存在。忽略它,这是因为如果您使用的是网络表单,该路径将映射到物理文件,但使用 MVC 时情况并非如此。

如果您希望允许用户注销以便 s/he 可以使用其他帐户登录,您还应该设置注销 url 因为在组方面没有任何要求:

<location path="Home/Logout">
    <system.web>
        <authorization>
            <allow Users="*"/>
        </authorization>
    </system.web>
</location> 

您现在应该处理到达 "pipeline" 末尾的请求,其中 401 Unauthorized 用户已通过身份验证,并将它们重定向到自定义未授权页面:

在 global.asax 中注册 EndRequest 事件并进行检查,将响应更改为 302 Found(临时重定向)到自定义未授权页面:

负责人:

protected MvcApplication(){
  EndRequest+=(s, e) => 
  {
    if (Response.StatusCode == 401 && User.Identity.IsAuthenticated)
    {
      Response.StatusCode = 302;
      Response.Headers.Add("Location", VirtualPathUtility.ToAbsolute("~/Error/Unauthorized"));
    }
  }
}

System.Web.VirtualPathUtility 在这里非常有用,因为它扩展了 ~ 并生成了完整的 url

位置 header 只是浏览器在收到 302 响应时使用的 header 的名称。然后它将执行对 url 的请求,即 header 值。

我确信 WSFederationAuthenticationModule 可以通过 web.config 中的设置满足这种情况,但我真的找不到它。

这里是 web.config 中的所有设置汇总:

<configuration>
 ...
    <location path="Error/Unauthorized">
        <system.web>
            <authorization>
                <allow Users="*"/>
            </authorization>
        </system.web>
    </location>
    <location path="Home/Logout">
        <system.web>
            <authorization>
                <allow Users="*"/>
            </authorization>
        </system.web>
    </location> 
    <system.web>
        <authentication mode="None" />
        <authorization>
           <allow roles="GroupA,GroupB,GroupC,GroupD"/>
           <deny users="*" />
        </authorization>
        ...
    </system.web>
    <system.identityModel>
    ....