我正在使用 ASP.NET MVC 4 Web 应用程序作为某些 WCF 服务的前端。所有用户登录/注销和会话控制都在后端完成。MVC 应用程序应该只存储一个带有会话 ID 的 cookie。我的客户端不允许使用表单身份验证,一切都必须自定义。
我在 web.config 中设置了以下内容:
<system.web>
...
<authentication mode="None" />
</system.web>
<system.webServer>
<modules>
...
<remove name="FormsAuthentication" />
...
</modules>
</system.webServer>
我还有一个全局过滤器:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// Force all actions to request auth. Only actions marked with [AllowAnonymous] will be allowed.
filters.Add(new MyAuthorizeAttribute());
}
}
在 Global.asax 中调用
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
我已经用 [AllowAnonymous] 标记了每个不需要授权的控制器和操作。
现在我必须实现 MyAuthorizeAttribute。我尝试了一些教程,但没有一个完全符合我的场景。
基本上,我必须为每个动作处理以下场景:
- 如果存在有效的 cookie,则应认为当前请求已授权(将不会检查任何角色,只有一种用户)。
- 如果没有 cookie,我应该覆盖默认的 MVC 处理程序(它尝试加载帐户/登录)并将用户重定向到主页/索引页面,并显示用户应该登录的消息。
- 如果 WCF 方法调用抛出 FaultException,而我们的自定义 SecurityFault 表示会话已过期(SecurityFault 有一个包含异常原因的自定义枚举字段),我应该销毁我的自定义会话 cookie 并再次将用户重定向到主页/索引页面用户应该登录的消息,因为他的最后一个会话已过期。对于所有其他 SecurityFaults,我可以让它们通过 - 我有一个全局错误处理程序。
据我了解,我需要重写 AuthorizeCore (检查我的 cookie 以查看会话是否存在并且仍然有效)和 HandleUnauthorizedRequest (将用户重定向到主页/索引而不是默认登录页面)。
对于重定向,我尝试过:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
filterContext.Result = new RedirectResult("/Home/Index/NeedsLogin");
}
这似乎可以很好地处理第二种情况(不过,我不确定那个基本调用 - 需要吗?)。
对于第一种情况,我需要实现 AuthorizeCore。我不确定,如何正确地做到这一点。我已经看到 AuthorizeAttribute 有一些用于处理缓存情况的代码,也许还有更多隐藏的功能,我不想破坏它。
对于第三种情况,我不确定 MyAuthorizeAttribute 是否能够处理它。AuthorizeAttribute 能否捕获 Action 内部发生的异常,或者我必须在全局错误处理程序中处理 SecurityFault.SessionExpired 情况?