用户在角色“管理员”,但[授权(角色=“管理员”)]将不验证
问题描述:
我发现了一个很好的回答在SO描述how to set up custom user roles,我在我的项目中也做了同样的。所以在我的登录服务,我有:用户在角色“管理员”,但[授权(角色=“管理员”)]将不验证
public ActionResult Login() {
// password authentication stuff omitted here
var roles = GetRoles(user.Type); // returns a string e.g. "admin,user"
var authTicket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddMinutes(20), // expiry
false,
roles,
"/");
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket));
Response.Cookies.Add(cookie);
return new XmlResult(xmlDoc); // don't worry so much about this - returns XML as ActionResult
}
而在Global.asax.cs中,我已经(从逐字其他答案复制):
protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null) {
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var roles = authTicket.UserData.Split(new Char[] { ',' });
var userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
然后,在我的ServicesController
类,我有:
[Authorize(Roles = "admin")]
//[Authorize]
public ActionResult DoAdminStuff() {
...
}
我以具有“管理员”角色的用户身份登录,并且工作正常。然后我调用/ services/doadminstuff - 即使在Global.asax.cs中放置断点时,我也可以看到我的角色包含“admin”。如果我注释掉第一个Authorize
属性(包含角色)并仅使用简单的香草Authorize
,那么我可以访问该服务。
我必须在这里丢失重要的东西 - 但从哪里开始寻找?
答
我会建议你使用自定义的授权属性,而不是Application_AuthenticateRequest
:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
string cookieName = FormsAuthentication.FormsCookieName;
if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
filterContext.HttpContext.Request.Cookies == null ||
filterContext.HttpContext.Request.Cookies[cookieName] == null
)
{
HandleUnauthorizedRequest(filterContext);
return;
}
var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(',');
var userIdentity = new GenericIdentity(authTicket.Name);
var userPrincipal = new GenericPrincipal(userIdentity, roles);
filterContext.HttpContext.User = userPrincipal;
base.OnAuthorization(filterContext);
}
}
然后:
[CustomAuthorize(Roles = "admin")]
public ActionResult DoAdminStuff()
{
...
}
也是一个非常重要的事情是要确保当你登录身份验证Cookie是因为你返回一个XML文件而发射。当您尝试访问url /services/doadminstuff
时,使用FireBug检查身份验证Cookie是否已正确发送。
答
我将在第一个改变主要分配:
Thread.CurrentPrincipal = userPrincipal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = userPrincipal;
}
为ASP.NET文件表示。
它的工作!谢谢!告诉我,为什么这个工作,但Global.asax.cs中没有? – 2011-03-15 16:32:05
再次感谢您的帮助!也许你也可以解释一下这个相关的问题:http://stackoverflow.com/q/6586156/7850 – 2011-07-05 16:57:01
谢谢,它的工作原理。我怎样才能进一步控制显示哪个页面和正确的消息。 – Timeless 2014-07-18 06:30:11