我已经在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;
}
}
}
控制器
[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的用户登录时,它会将他重定向到正常页面,这正是我所需要的,但当用户通过身份验证时,他甚至可以访问其他页面。我想我需要处理一些请求。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中,当用户登录时,它显然会返回true,而不考虑IsAdmin是0还是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")]
MVC提供了一个称为过滤器的功能,它适用于那些需要保护某些控制器操作的场景。
过滤器可以用作属性或全局过滤器。
简单地在谷歌上搜索"MVC安全过滤器"应该会给你足够的信息。。。
实现你自己的安全过滤器,检查你的自定义权限会做你想做的事,我想。。。