我正在尝试在MVC3中做一件简单的事情。
我有一个应用程序,它使用表单身份验证来验证具有第三方SSO的用户。成功登录后,SSO会回复我的应用程序上的特定控制器操作。然后我拨打FormsAuthentication.SetAuthCookie(user,false);
。
我正在尝试实施某种程度的授权。简单地说,用户可以存在许多不同的角色,例如Admin
和Developer
。某些控制器操作应仅适用于某些角色。通过调用另一个外部API来获取用户所属角色的详细信息,该API返回一个简单的JSON响应指示。
理论上,在设置FormsAuthentication cookie后,这应该像执行此类操作一样简单:
string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
HttpContext.User = new GenericPrincipal(User.Identity, rolelist);
但是,在调用SetAuthCookie
后我无法直接调用此内容,因为HttpContext.User
此时没有任何意义。
我可以尝试在每个请求上设置此项,但是对我的应用程序的请求将意味着进行往返API调用。
到目前为止,我见过的最有希望的方法是创建自定义Authorization属性并覆盖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旅行。
最好的办法是什么?
答案 0 :(得分:2)
您应该覆盖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
<强>更新强>
我的方法签名错误(只在我自己的应用程序中检查过)。
答案 1 :(得分:2)
另一种方法是将角色存储在FormsAuthentcationTicket的UserData属性中。这可以用逗号分隔的字符串来完成。
然后在AuthenticateRequest方法上,您可以拉回故障单,获取角色数据并使用通用主体将其分配给当前用户。
答案 2 :(得分:1)
我首先想到的是您应该调查实现自定义角色提供程序。这可能是矫枉过正,但似乎适合基于角色的管道。
来自MSDN here的更多信息。
答案 3 :(得分:1)
令人骇人听闻的是,会话对象ISNT在这里是一个坏主意。 如果您使用临时数据,则您已经为该会话命中了一个。
将这些数据存储在cookie中,从一年半前开始,表单身份验证令牌已经在POET漏洞中被利用了,所以在这种情况下,有人可以简单地用“admin”字符串形成自己的cookie在其中使用该漏洞。
你可以在@jgauffin提到的post authenticate中执行此操作。 如果会话状态不可用,那么您可以在Application_PreRequestHandlerExecute中使用它并在那里进行检查。
如果您想检查会话状态是否可用,请参阅我的代码: How can I handle forms authentication timeout exceptions in ASP.NET?
每当使用表单身份验证和会话时,您总是希望确保超时彼此同步(再次使用上面的代码)