基本上,我在过去的几天里一直在试图弄清楚如何将简单的管理员和成员角色添加到我为朋友开发的网站上。(我使用的是ASP.NET框架5.2.7.0)。我知道微软内置了一个很好的基于角色的访问功能,它允许你在控制器的顶部放置一些类似[Authorize Role=("Admin")的东西;然而,我根本无法让它工作,我找到的大部分资源都是用于ASP.NET核心的。
我已经尝试修改我的web.config文件以启用基于角色的访问(希望将角色等迁移到我的数据库中)。但由于我一直无法弄清楚这一切,我尝试了一条更老套的路线。(**我不是一个高级程序员,我已经做了大约一年了,我不是一个专业的程序员)。这就是我在尝试验证用户是否是管理员时想出的方法(这也不起作用)。
[Authorize]
public class AdminController : Controller
{
private LDSXpressContext db = new LDSXpressContext();
public ActionResult AdminPortal()
{
IsAdmin();
return View();
}
private ActionResult IsAdmin()
{
string name = User.Identity.Name;
//The User.Identity.Name stores the user email when logged in
var currentUserObject = db.accounts.Where(x => x.clientEmail == name);
Account currentUser = new Account();
foreach (var user in currentUserObject)
{
//I loop through the results, even though only one user should
//be stored in the var CurrentUserObject because it's the only
//way I know how to assign it to an object and get its values.
currentUser = user;
}
if (currentUser.role == 2) //the number 2 indicates admin in my db
{
return null;
}
else
{
//Even when this is hit, it just goes back and returns the
//AdminPortal view
return RedirectToAction("Index", "Home");
}
}
}现在我几乎可以肯定,这不是一个非常安全的方式来检查一个登录的用户是否是管理员,但我希望它至少能起作用。我的想法是,当有人试图访问AdminPortal时,IsAdmin方法将运行并检查该用户是否为数据库中的管理员。如果他们是管理员,则返回null并显示AdminPortal视图;如果他们不是管理员,则将他们重定向到主页上的索引视图。但是,AdminPortal页面总是显示给任何用户,这似乎也不起作用。我甚至深入到代码中,看着它在return RedirectToAction("Index", "Home");操作上运行,但随后它又跳回AdminPortal方法,只返回AdminPortal视图。所以我的问题是:
1)如果任何人碰巧有在ASP.NET框架中使用基于角色的访问的经验,我想要一些关于如何设置它的提示
或,
2)如果所有其他方法都失败了,我需要使用我的hacky方法,为什么即使用户不是管理员,它仍然返回AdminView。
**注意:我知道我可以创建一个函数,无论用户是不是管理员,都返回true或false,然后在AdminPortal控制器中有一个if/else语句,它将在视图上返回true,另一个返回false,但是我不想在每个ActionMethod上都实现它,如果可能的话,最好将它保持在一行,或者只在控制器上方的[Authorize Role="Admin]上。
非常感谢你们提供的任何帮助,我已经尝试了几天的研究和解决这个问题,并决定联系并询问社区!
发布于 2019-06-26 10:19:09
至少,你需要对你正在做的事情做一些调整:
[Authorize]
public class AdminController : Controller
{
public ActionResult AdminPortal()
{
if(IsAdmin())
{
return View();
}
return RedirectToAction("Index", "Home");
}
private bool IsAdmin()
{
bool isAdmin = false;
using(LDSXpressContext db = new LDSXpressContext())
{
string name = User.Identity.Name;
//The User.Identity.Name stores the user email when logged in
// @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.singleordefault
var currentUser = db.accounts.SingleOrDefault(x => x.clientEmail.Equals(name, StringComparison.OrdinalIgnoreCase));
// If the email doesn't match a user, currentUser will be null
if (currentUser != null)
{
//the number 2 indicates admin in my db
isAdmin = currentUser.role == 2;
}
}
return isAdmin;
}
}首先,DbContext实例最多只能在HTTP请求的生命周期内使用。将它从类/控制器级别移出,并将其放在using块中可以确保它得到了正确的处理。
接下来,您的IsAdmin函数实际上只需要根据查找返回一个true/false值,然后AdminPortal操作就可以决定如何处理该结果。
由于电子邮件似乎是表中的唯一字段,因此请使用SingleOrDefault或FirstOrDefault LINQ扩展来获取单个匹配记录。您可以自行决定使用哪一个值,但如果它确实是一个惟一的值,则SingleOrDefault更有意义(如果有多个行匹配,它将抛出异常)。在String.Equals扩展方法中使用StringComparison标志可以使搜索不区分大小写。有一些特定于文化的版本,但我在这里通常会使用序号匹配。
实现某个版本的身份框架对于这里的答案来说有点太长了,但是可以在不做太多工作的情况下实现基于声明的身份验证方案。不过,这可能需要一个单独的答案。
https://stackoverflow.com/questions/56764019
复制相似问题