当使用 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>
....
我的 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>
....