MVC3 中具有窗体身份验证的简单授权



我正在尝试在MVC3中做一件简单的事情。

我有一个使用表单身份验证的应用程序,通过第三方 SSO 对用户进行身份验证。成功登录后,SSO 将回发到我的应用程序上的特定控制器操作。然后我打电话给FormsAuthentication.SetAuthCookie(user,false);.

我正在尝试实现某种程度的授权。简单地说,用户可以以许多不同的角色存在,例如 AdminDeveloper.某些控制器操作应仅适用于某些角色。用户所属角色的详细信息是通过调用另一个外部 API 来获取的,该 API 返回指示的简单 JSON 响应。

从理论上讲,这应该像在我设置 FormsAuthentication cookie 后执行类似操作一样简单:

string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
HttpContext.User = new GenericPrincipal(User.Identity, rolelist);

但是,我不能在调用SetAuthCookie后直接调用它,因为此时HttpContext.User没有任何意义。

我可以尝试在每个请求上设置它,但对我的应用程序的任何请求都意味着往返 API 调用。

到目前为止,我看到的最有希望的方法是创建自定义授权属性并覆盖OnAuthorization以执行以下操作:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if (<some way of checking if roles have already been set for this user, or role cache has timed out>)
    {
        string[] rolelist = GetRoleListForUserFromAPI(filterContext.HttpContext.User.Identity.Name);
        filterContext.HttpContext.User = new GenericPrincipal(filterContext.HttpContext.User.Identity,rolelist);
    }
}

然后,我可以在控制器操作之前使用[MyCustomAuthorization(Roles="Admin")]来使魔术发生。

但是,我不知道如何检测当前HttpContext.User对象是否已设置其角色,或者它是否在某个时间之前设置,并且需要另一个 API 之旅。

最好的

方法是什么?

另一种方法是将角色存储在 FormsAuthentcationTicket 的 UserData 属性中。这可以使用逗号分隔的字符串来完成。

http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationticket.formsauthenticationticket

然后,在 AuthenticateRequest 方法上,您可以拉回票证,获取角色数据并使用通用主体将其分配给当前用户。

你应该覆盖PostAuthenticateRequest

protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e) 
{
    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
        HttpContext.User = new GenericPrincipal(User.Identity, rolelist);
    }
}

在窗体身份验证完成处理后

调用它。

http://msdn.microsoft.com/en-us/library/ff647070.aspx

更新

我有错误的方法签名(刚刚在我自己的一个应用程序中检查过)。

我的第一个想法是,您应该研究实现自定义角色提供程序。 这可能有点矫枉过正,但似乎适合基于角色的管道。

来自 MSDN 的更多信息,请单击此处。

令一些人震惊的是,会话对象在这里是一个坏主意。如果使用临时数据,则会话已经受到打击。

将这些数据存储在cookie中,好吧 - 从一年半前开始,表单身份验证令牌已经在POET漏洞中被利用,因此在这种情况下,有人可以使用该漏洞简单地使用"admin"字符串形成自己的cookie。

您可以按照@jgauffin所述在身份验证后执行此操作。如果会话状态在那里不可用,您可以在Application_PreRequestHandlerExecute中使用它并在那里检查它。

如果要检查会话状态是否可用,请参阅我的代码:如何在 ASP.NET 中处理表单身份验证超时异常?

此外,每当使用表单身份验证和会话时,您始终希望确保超时彼此同步(再次使用上面的代码)

最新更新