【问题标题】:Authorize Attribute with Roles使用角色授权属性
【发布时间】:2019-12-07 20:35:37
【问题描述】:

我想实现我的自定义授权,我想知道我的代码有什么问题,即使我正确获取了用户凭据,它仍然会将我重定向到我的登录方法,请参阅下面的代码

编辑:我已经成功实现了带角色的授权属性,未来的读者请看下面的代码

登录控制器

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
{
    if (!ModelState.IsValid)
    {
        return View(viewModel);
    }
    PasswordHasher passwordVerify = new PasswordHasher();
    var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
                select new { acc.username, acc.password}).FirstOrDefault();
    if (query != null)
    {
        if (ModelState.IsValid)
        {
            var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
            switch (result)
            {
                case PasswordVerificationResult.Success:
//set forms ticket to be use in global.asax
                    SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
                    return RedirectToLocal(returnURL);
                case PasswordVerificationResult.Failed:
                    ModelState.AddModelError("", "Wrong Username or Password");
                    return View(viewModel);
            }
        }
    }
    return View(viewModel);
}

表单验证票

private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
{
    account user = new account();
    var userId = user.id;
    var userData = userId.ToString(CultureInfo.InvariantCulture);
    var authTicket = new FormsAuthenticationTicket(1, //version
                        userName, // user name
                        DateTime.Now,             //creation
                        DateTime.Now.AddMinutes(20), //Expiration
                        persistanceFlag, //Persistent
                        userData);

    var encTicket = FormsAuthentication.Encrypt(authTicket);
    Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
    return user;
}

全球.asax

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        if (FormsAuthentication.CookiesSupported == true)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    //take out user name from cookies              
                    string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
                    string[] roles = null;

                    trainingEntities db = new trainingEntities();
                    //query database to get user roles
                    var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
                    roles = query;

                    //Let us set the Pricipal with our user specific details
                    HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
                      new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
                }
                catch (Exception)
                {
                    //somehting went wrong
                }
            }
        }
    } 

现在你可以使用[Authorize(Roles = "Admin")]

到任何操作方法或在控制器之上

【问题讨论】:

  • return userrole.role_name; in ReturnUserRole() 实际返回了什么?
  • 它应该返回指定用户名的角色。
  • 很好奇为什么你有select new {acc.account.username, acc_roles.role.role_name} 但只使用第二个值。那么为什么当你只返回一个值时你有var roles = string.Join(...)
  • 我已经更新了我的代码..
  • 这更有意义:) 你真的打了var roles = ReturnUserRole(..) 行吗? this.UserRole 的值是多少?

标签: asp.net-mvc authorize-attribute


【解决方案1】:

我已经成功实现了带角色的授权属性,未来的读者请看下面的代码。

登录控制器

            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
            {
                if (!ModelState.IsValid)
                {
                    return View(viewModel);
                }
                PasswordHasher passwordVerify = new PasswordHasher();
                var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
                            select new { acc.username, acc.password}).FirstOrDefault();
                if (query != null)
                {
                    if (ModelState.IsValid)
                    {
                        var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
                        switch (result)
                        {
                            case PasswordVerificationResult.Success:
                               //set forms ticket to be use in global.asax
                                SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
                                return RedirectToLocal(returnURL);
                            case PasswordVerificationResult.Failed:
                                ModelState.AddModelError("", "Wrong Username or Password");
                                return View(viewModel);

                        }
                    }
                }
                return View(viewModel);

            }

FormsAuthTicket

  private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
    {
        account user = new account();
        var userId = user.id;
        var userData = userId.ToString(CultureInfo.InvariantCulture);
        var authTicket = new FormsAuthenticationTicket(1, //version
                            userName, // user name
                            DateTime.Now,             //creation
                            DateTime.Now.AddMinutes(20), //Expiration
                            persistanceFlag, //Persistent
                            userData);

        var encTicket = FormsAuthentication.Encrypt(authTicket);
        Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
        return user;
    }

全球.asax

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        if (FormsAuthentication.CookiesSupported == true)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    //take out user name from cookies              
                    string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
                    string[] roles = null;

                    trainingEntities db = new trainingEntities();
                    //query database to get user roles
                    var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
                    roles = query;

                    //Let us set the Pricipal with our user specific details
                    HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
                      new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
                }
                catch (Exception)
                {
                    //somehting went wrong
                }
            }
        }
    } 

现在你可以使用[Authorize(Roles = "Admin")]

到任何操作方法或在控制器之上

【讨论】:

    【解决方案2】:

    正如我在 ControllerLogin 属性中看到的,它现在被应用到变量中,当它应该被应用到方法或类时

     [CustomAuthorization(UserRole="Admin")]
     // GET: Manage
     private trainingEntities db = new trainingEntities();
     public ActionResult Index()
     {
         return View();
     }
    
    
    Private trainingEntities dB = new TrainingEntities();
    
    [CustomAuthorization(UserRole="Admin")]
    Public ActionResult Index()
    {
       //yourcode
    }
    

    【讨论】:

    • 如果在变量上,会出现错误消息,因为 attribute 只允许在类或方法上。
    猜你喜欢
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2011-09-03
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    相关资源
    最近更新 更多