我在MVC4中开发了一个Web API,我正在进行身份验证和授权。 我有不同类型的用户,他们应该对API有不同的看法。 所以,我刚刚创建了一个包含IsAdmin列的用户的表,其中很少有人将其作为1而其他人为0.
我编写了一种方法来检查他使用的用户类型
public bool IsValidAdmin(string _username, string _password)
{
using (var cn = new SqlConnection(@"Data Source=xyz.com;Initial Catalog=pqr;Persist Security Info=True;User ID=abc;Password=****"))
{
string _sql = @"SELECT [Username] FROM [dbo].[System_Users] " +
@"WHERE [Username] = @u AND [Password] = @p AND [IsAdmin]=1";
var cmd = new SqlCommand(_sql, cn);
cmd.Parameters.AddWithValue("@u",_username);
cmd.Parameters.AddWithValue("@p", _password);
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Dispose();
cmd.Dispose();
return true;
}
else
{
reader.Dispose();
cmd.Dispose();
return false;
}
}
}
public bool IsValidUser(string _username, string _password)
{
using (var cn = new SqlConnection(@"Data Source=xyz.com;Initial Catalog=pqr;Persist Security Info=True;User ID=abc;Password=****"))
{
string _sql = @"SELECT [Username] FROM [dbo].[System_Users] " +
@"WHERE [Username] = @u AND [Password] = @p AND [IsAdmin]!=1";
var cmd = new SqlCommand(_sql, cn);
cmd.Parameters.AddWithValue("@u", _username);
cmd.Parameters.AddWithValue("@p", _password);
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Dispose();
cmd.Dispose();
return true;
}
else
{
reader.Dispose();
cmd.Dispose();
return false;
}
}
}
CONTROLLER
[HttpPost]
public ActionResult Login(Models.User user)
{
if (ModelState.IsValid)
{
if (user.IsValidAdmin(user.UserName, user.Password))
{
FormsAuthentication.SetAuthCookie(user.UserName, user.RememberMe);
return RedirectToAction("Index", "Admin");
}
else if (user.IsValidUser(user.UserName, user.Password))
{
FormsAuthentication.SetAuthCookie(user.UserName, user.RememberMe);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Login data is incorrect!");
}
}
return View(user);
管理
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
[Authorize]
public ActionResult Index()
{
return View();
}
普通用户
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
[Authorize]
public ActionResult Index() {
return View();
}
当用户使用IsAdmin = 0登录时,它会将其重定向到正常页面,这是我需要的,但他甚至可以在用户通过身份验证时访问其他页面。 我认为我需要处理request.IsAuthenticated在我的母版页中如下
Layout.cshtml
@if (Request.IsAuthenticated)
{
<tr>
<td class="btn">@Html.ActionLink(@Html.Encode(User.Identity.Name).ToUpper()+"!!","Index","Admin")</td>
<td class="btn"> @Html.ActionLink("Sign Out", "Logout", "User")</td>
</tr>
}
else
{
<tr>
<td class="User btn">
@Html.ActionLink("Sign In", "Login", "User")</td></tr>
}
现在在Request.IsAuthenticated中的上述cshtml中,当用户登录而不考虑IsAdmin是0还是1时,它显然会返回true,并且因为它可以访问所有页面。
我是否知道某种方法可以避免这种情况并拒绝访问内部页面?
答案 0 :(得分:1)
MVC提供了一个名为Filters的功能,适用于您希望保护某些控制器操作的场景。
过滤器可用作属性或全局过滤器。
简单地谷歌“MVC安全过滤器”应该给你足够的信息......
实施您自己的安全过滤器,检查您的自定义权限是否符合您的意思...
答案 1 :(得分:1)
您需要创建自定义AuthorizeAttribute
,以便将其作为过滤器应用于控制器中您希望进行更精细控制的特定操作。
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public bool IsAdmin {get; set;}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Load user permissions here
if(IsAdmin) return user.IsAdmin;
return false;
}
}
然后您可以在控制器中的特定操作上使用它,如下所示:
[CustomAuthorize(IsAdmin = true)]
public ActionResult AdminOnlyAction()
{
}
如果您想要过滤许多特定权限,最好只使用字符串作为角色,然后根据这些角色测试用户。
[CustomAuthorize(Roles = "admin,superadmin")]