授权属性在 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;
    }
}