授权属性在 MVC 中不起作用
Authorize attribute doesn't work in MVC
我有一个角色为 Member
的用户。我有这个登录操作:
public virtual ActionResult Login(string returnUrl)
{
if(User.Identity.IsAuthenticated)
{
if (IsValidReturnUrl(returnUrl))
return Redirect(returnUrl);
return Redirect(FormsAuthentication.DefaultUrl);
}
return View();
}
我有这个 ActionMethod :
[Authorize(Roles="Member")]
public virtual ActionResult PostLostThing()
{
var maingroups = _maingroups.SelectAll();
var Provinces = _provinces.SelectAll();
ViewBag.MainGroups = new SelectList(maingroups, "GroupId", "GroupName", maingroups.FirstOrDefault().GroupId);
ViewBag.SubGroups = new SelectList(maingroups.FirstOrDefault().SubGroups, "id", "name");
ViewBag.Provinces = new SelectList(Provinces, "Id", "Title", Provinces.FirstOrDefault().Id);
ViewBag.Cities = new SelectList(Provinces.FirstOrDefault().Cities, "Id", "Name");
return View();
}
当用户登录并调用视图 PostLostThing
时,它会重定向到登录页面,但是当删除 Authorize
属性的 Role
时,它工作得很好。我有这个 SetAuthCookie
方法:
private void SetAuthCookie(string memberName, string roleofMember, bool presistantCookie)
{
var timeout = presistantCookie ? FormsAuthentication.Timeout.TotalMinutes : 30;
var now = DateTime.UtcNow.ToLocalTime();
var expirationTimeSapne = TimeSpan.FromMinutes(timeout);
var authTicket = new FormsAuthenticationTicket(
1,
memberName,
now,
now.Add(expirationTimeSapne),
presistantCookie,
roleofMember,
FormsAuthentication.FormsCookiePath
);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (FormsAuthentication.CookieDomain != null)
{
authCookie.Domain = FormsAuthentication.CookieDomain;
}
if (presistantCookie)
authCookie.Expires = DateTime.Now.AddMinutes(timeout);
Response.Cookies.Add(authCookie);
}
有什么问题?
由于您自己设置了 auth cookie,因此您需要在 Global.asax.cs 文件中实现 Application_AuthenticateRequest
。否则,除用户名外,不会向 Principal 对象添加任何内容。
这是一个示例实现:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = null;
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
您使用的重载假定您传递的值 roleofMember
实际上是一些序列化数据。然后,您需要告诉它如何处理反序列化该用户数据。由于您只是传递一个角色名称,您可以将上面的示例修改为:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = new string [] { authTicket.UserData };
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
我有一个角色为 Member
的用户。我有这个登录操作:
public virtual ActionResult Login(string returnUrl)
{
if(User.Identity.IsAuthenticated)
{
if (IsValidReturnUrl(returnUrl))
return Redirect(returnUrl);
return Redirect(FormsAuthentication.DefaultUrl);
}
return View();
}
我有这个 ActionMethod :
[Authorize(Roles="Member")]
public virtual ActionResult PostLostThing()
{
var maingroups = _maingroups.SelectAll();
var Provinces = _provinces.SelectAll();
ViewBag.MainGroups = new SelectList(maingroups, "GroupId", "GroupName", maingroups.FirstOrDefault().GroupId);
ViewBag.SubGroups = new SelectList(maingroups.FirstOrDefault().SubGroups, "id", "name");
ViewBag.Provinces = new SelectList(Provinces, "Id", "Title", Provinces.FirstOrDefault().Id);
ViewBag.Cities = new SelectList(Provinces.FirstOrDefault().Cities, "Id", "Name");
return View();
}
当用户登录并调用视图 PostLostThing
时,它会重定向到登录页面,但是当删除 Authorize
属性的 Role
时,它工作得很好。我有这个 SetAuthCookie
方法:
private void SetAuthCookie(string memberName, string roleofMember, bool presistantCookie)
{
var timeout = presistantCookie ? FormsAuthentication.Timeout.TotalMinutes : 30;
var now = DateTime.UtcNow.ToLocalTime();
var expirationTimeSapne = TimeSpan.FromMinutes(timeout);
var authTicket = new FormsAuthenticationTicket(
1,
memberName,
now,
now.Add(expirationTimeSapne),
presistantCookie,
roleofMember,
FormsAuthentication.FormsCookiePath
);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (FormsAuthentication.CookieDomain != null)
{
authCookie.Domain = FormsAuthentication.CookieDomain;
}
if (presistantCookie)
authCookie.Expires = DateTime.Now.AddMinutes(timeout);
Response.Cookies.Add(authCookie);
}
有什么问题?
由于您自己设置了 auth cookie,因此您需要在 Global.asax.cs 文件中实现 Application_AuthenticateRequest
。否则,除用户名外,不会向 Principal 对象添加任何内容。
这是一个示例实现:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = null;
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
您使用的重载假定您传递的值 roleofMember
实际上是一些序列化数据。然后,您需要告诉它如何处理反序列化该用户数据。由于您只是传递一个角色名称,您可以将上面的示例修改为:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = new string [] { authTicket.UserData };
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}