使用身份验证创建不同的访问级别
Creating varying access levels using authentication
我创建了一个具有安全访问级别的枚举,例如:
public enum AccessLevel
{
Total,
DeletionPrivileges,
MaintainUsers,
MaintainInventory,
QueriesOnly,
None
}
我可以管理站点,因此某些功能(例如删除)不会显示给没有删除权限的人。但我也想在代码中使用某种授权。
在默认框架内,使用 [Authorize]
可以防止访问项目的某些区域,我如何创建不同级别的权限来标记每个方法?
您可以使用 Identity 的基于声明的身份验证功能轻松实现此目的。首先,您需要在登录操作方法中为每个用户添加正确的声明,这样更改您的登录操作方法:
[HttpPost]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var userManager=HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = userManager.Find(model.UserName, model.Password);
if (user != null)
{
var ident = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
// imaging you have a custom class which return user access levels
var userAccessLevels=_accessLevelManager.GetAccessLevels(user.Id);
// now we are going to add our custom claims
ident.AddClaims(new[]
{
// add each access level as a separate claim
new Claim("AccessLevel",userAccessLevels[0].ToString()),
new Claim("AccessLevel",userAccessLevels[1].ToString()),
// and so on
});
HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);
// authentication succeed do what you want
return Redirect(login.ReturnUrl ?? Url.Action("Index", "Home"));
}
}
ModelState.AddModelError("", "Invalid username or password");
return View(login);
}
现在我们已经成功地将声明注入到 Identity 中。但是您需要一个自定义授权属性来检查您的声明,如下所示:
public class ClaimsAccessAttribute : AuthorizeAttribute
{
public string ClaimType { get; set; }
public string Value { get; set; }
protected override bool AuthorizeCore(HttpContextBase context)
{
return context.User.Identity.IsAuthenticated
&& context.User.Identity is ClaimsIdentity
&& ((ClaimsIdentity)context.User.Identity).HasClaim(x =>
x.Type == ClaimType && x.Value == Value);
}
}
现在您可以轻松地在您的操作方法中使用您的属性:
[ClaimsAccess(CliamType="AccessLevel",Value="DeletionPrivileges")]
public ActionResult MyAction()
{
// also you have access the authenticated user's claims
// simply by casting User.Identity to ClaimsIdentity
// ((ClaimsIdentity)User.Identity).Claims
}
我创建了一个具有安全访问级别的枚举,例如:
public enum AccessLevel
{
Total,
DeletionPrivileges,
MaintainUsers,
MaintainInventory,
QueriesOnly,
None
}
我可以管理站点,因此某些功能(例如删除)不会显示给没有删除权限的人。但我也想在代码中使用某种授权。
在默认框架内,使用 [Authorize]
可以防止访问项目的某些区域,我如何创建不同级别的权限来标记每个方法?
您可以使用 Identity 的基于声明的身份验证功能轻松实现此目的。首先,您需要在登录操作方法中为每个用户添加正确的声明,这样更改您的登录操作方法:
[HttpPost]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var userManager=HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = userManager.Find(model.UserName, model.Password);
if (user != null)
{
var ident = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
// imaging you have a custom class which return user access levels
var userAccessLevels=_accessLevelManager.GetAccessLevels(user.Id);
// now we are going to add our custom claims
ident.AddClaims(new[]
{
// add each access level as a separate claim
new Claim("AccessLevel",userAccessLevels[0].ToString()),
new Claim("AccessLevel",userAccessLevels[1].ToString()),
// and so on
});
HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);
// authentication succeed do what you want
return Redirect(login.ReturnUrl ?? Url.Action("Index", "Home"));
}
}
ModelState.AddModelError("", "Invalid username or password");
return View(login);
}
现在我们已经成功地将声明注入到 Identity 中。但是您需要一个自定义授权属性来检查您的声明,如下所示:
public class ClaimsAccessAttribute : AuthorizeAttribute
{
public string ClaimType { get; set; }
public string Value { get; set; }
protected override bool AuthorizeCore(HttpContextBase context)
{
return context.User.Identity.IsAuthenticated
&& context.User.Identity is ClaimsIdentity
&& ((ClaimsIdentity)context.User.Identity).HasClaim(x =>
x.Type == ClaimType && x.Value == Value);
}
}
现在您可以轻松地在您的操作方法中使用您的属性:
[ClaimsAccess(CliamType="AccessLevel",Value="DeletionPrivileges")]
public ActionResult MyAction()
{
// also you have access the authenticated user's claims
// simply by casting User.Identity to ClaimsIdentity
// ((ClaimsIdentity)User.Identity).Claims
}