您的位置:首页 > 编程语言 > ASP

asp.net core策略授权

2019-08-20 16:40 926 查看
原文链接:https://blog.51cto.com/axzxs/1962246?source=drh

首先看基于角色组,或用户名,或基于ClaimType或自定义键值等授权策略,这些都是通过Services.AddAuthorization添加,并且是AuthorizationOptions来AddPolicy,这里策略的名称统一用RequireClaim来命名,不同的请求的策略名称各不相同,如用户名时就用policy.RequireUserName(),同时,在登录时,验证成功后,要添加相应的Claim到ClaimsIdentity中:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization(options =>
{
//基于角色的策略
options.AddPolicy("RequireClaim", policy => policy.RequireRole("admin", "system"));
//基于用户名
//options.AddPolicy("RequireClaim", policy => policy.RequireUserName("桂素伟"));
//基于Claim
//options.AddPolicy("RequireClaim", policy => policy.RequireClaim(ClaimTypes.Country,"中国"));
//自定义值
// options.AddPolicy("RequireClaim", policy => policy.RequireClaim("date","2017-09-02"));

}).AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>{
options.LoginPath = new PathString("/login");
options.AccessDeniedPath = new PathString("/denied");
});
}

HomeController.cs

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PolicyPrivilegeManagement.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
namespace PolicyPrivilegeManagement.Controllers
{
[Authorize(Policy = “RequireClaim”)]
public class HomeController : Controller
{
PermissionHandler _permissionHandler;
public HomeController(IAuthorizationHandler permissionHandler)
{
_permissionHandler = permissionHandler as PermissionHandler;
}
public IActionResult Index()
{
return View();
}
public IActionResult PermissionAdd()
{
return View();
}

public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[AllowAnonymous]
[HttpGet("login")]
public IActionResult Login(string returnUrl = null)
{
TempData["returnUrl"] = returnUrl;
return View();
}
[AllowAnonymous]
[HttpPost("login")]
public async Task<IActionResult> Login(string userName, string password, string returnUrl = null)
{
var list = new List<dynamic> {
new { UserName = "gsw", Password = "111111", Role = "admin",Name="桂素伟",Country="中国",Date="2017-09-02",BirthDay="1979-06-22"},
new { UserName = "aaa", Password = "222222", Role = "system",Name="测试A" ,Country="美国",Date="2017-09-03",BirthDay="1999-06-22"}
};
var user = list.SingleOrDefault(s => s.UserName == userName && s.Password == password);
if (user != null)
{
//用户标识
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Sid, userName));
identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
identity.AddClaim(new Claim(ClaimTypes.Role, user.Role));
identity.AddClaim(new Claim(ClaimTypes.Country, user.Country));
identity.AddClaim(new Claim("date", user.Date));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
if (returnUrl == null)
{
returnUrl = TempData["returnUrl"]?.ToString();
}
if (returnUrl != null)
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
else
{
const string badUserNameOrPasswordMessage = "用户名或密码错误!";
return BadRequest(badUserNameOrPasswordMessage);
}
}
[HttpGet("logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
[AllowAnonymous]
[HttpGet("denied")]
public IActionResult Denied()
{
return View();
}
}

}
上面的授权策略都相对简单,单一,使用场景也很有限,就和固定角色授权如出一辙,其实可以用更好的来例用授权,那就是自定义授权Handler,我们在《asp.net core认证与授权》一文中,是通过中间件来达到自定义解色的,现在我们换个思路,通过自定义授权Handler来实现。

首先定义一个UserPermission,即用户权限实体类

/// <summary>
/// 用户权限
/// </summary>
public class UserPermission
{
/// <summary>
/// 用户名
/// </summary>
public string UserName
{ get; set; }
/// <summary>
/// 请求Url
/// </summary>
public string Url
{ get; set; }
}

接下来定义一个PermissionRequirement,为请求条件实体类

/// <summary>
/// 必要参数类
/// </summary>
public class PermissionRequirement : IAuthorizationRequirement
{
/// <summary>
/// 用户权限集合
/// </summary>
public  List<UserPermission> UserPermissions { get;private set; }
/// <summary>
/// 无权限action
/// </summary>
public string DeniedAction { get; set; }
/// <summary>
/// 构造
/// </summary>
/// <param name="deniedAction">无权限action</param>
/// <param name="userPermissions">用户权限集合</param>
public PermissionRequirement(string deniedAction, List<UserPermission> userPermissions)
{
DeniedAction = deniedAction;
UserPermissions = userPermissions;
}
}

再定义自定义授权Hanlder,我们命名为PermissionHandler,此类必需继承AuthorizationHandler,只用实现public virtualTask HandleAsync(AuthorizationHandlerContext context),些方法是用户请求时验证是否授权的主方法,所以实现与自定义角色中间件的Invoke很相似。

using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace PolicyPrivilegeManagement.Models
{
///
/// 权限授权Handler
///
public class PermissionHandler : AuthorizationHandler
{
///
/// 用户权限
///
public List UserPermissions { get; set; }
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
//赋值用户权限
UserPermissions = requirement.UserPermissions;
//从AuthorizationHandlerContext转成HttpContext,以便取出表求信息
var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext;
//请求Url
var questUrl = httpContext.Request.Path.Value.ToLower();
//是否经过验证
var isAuthenticated = httpContext.User.Identity.IsAuthenticated;
if (isAuthenticated)
{
if (UserPermissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0)
{
//用户名
var userName = httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Sid).Value;
if (UserPermissions.Where(w => w.UserName == userName && w.Url.ToLower() == questUrl).Count() > 0)
{
context.Succeed(requirement);
}
else
{
//无权限跳转到拒绝页面
3ff7 httpContext.Response.Redirect(requirement.DeniedAction);
}
}
else
{
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
}
此次的Startup.cs的ConfigureServices发生了变化,如下

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization(options =>
{
//自定义Requirement,userPermission可从数据库中获得
var userPermission = new List<UserPermission> {
new UserPermission {  Url="/", UserName="gsw"},
new UserPermission {  Url="/home/permissionadd", UserName="gsw"},
new UserPermission {  Url="/", UserName="aaa"},
new UserPermission {  Url="/home/contact", UserName="aaa"}
};
options.AddPolicy("Permission",
policy => policy.Requirements.Add(new PermissionRequirement("/denied", userPermission)));
}).AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>{
options.LoginPath = new PathString("/login");
options.AccessDeniedPath = new PathString("/denied");
});
//注入授权Handler
services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
}

HomeController中代码如下:

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PolicyPrivilegeManagement.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
namespace PolicyPrivilegeManagement.Controllers
{
[Authorize(Policy = “Permission”)]
public class HomeController : Controller
{
PermissionHandler _permissionHandler;
public HomeController(IAuthorizationHandler permissionHandler)
{
_permissionHandler = permissionHandler as PermissionHandler;
}
public IActionResult Index()
{
return View();
}
public IActionResult PermissionAdd()
{
return View();
}
[HttpPost(“addpermission”)]
public IActionResult AddPermission(string url,string userName)
{
//添加权限
_permissionHandler.UserPermissions.Add(new UserPermission { Url = url, UserName = userName });
return Content(“添加成功”);
}

public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[AllowAnonymous]
[HttpGet("login")]
public IActionResult Login(string returnUrl = null)
{
TempData["returnUrl"] = returnUrl;
return View();
}
[AllowAnonymous]
[HttpPost("login")]
public async Task<IActionResult> Login(string userName, string password, string returnUrl = null)
{
var list = new List<dynamic> {
new { UserName = "gsw", Password = "111111", Role = "admin",Name="桂素伟",Country="中国",Date="2017-09-02",BirthDay="1979-06-22"},
new { UserName = "aaa", Password = "222222", Role = "system",Name="测试A" ,Country="美国",Date="2017-09-03",BirthDay="1999-06-22"}
};
var user = list.SingleOrDefault(s => s.UserName == userName && s.Password == password);
if (user != null)
{
//用户标识
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Sid, userName));
identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
identity.AddClaim(new Claim(ClaimTypes.Role, user.Role));
identity.AddClaim(new Claim(ClaimTypes.Country, user.Country));
identity.AddClaim(new Claim("date", user.Date));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
if (returnUrl == null)
{
returnUrl = TempData["returnUrl"]?.ToString();
}
if (returnUrl != null)
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
else
{
const string badUserNameOrPasswordMessage = "用户名或密码错误!";
return BadRequest(badUserNameOrPasswordMessage);
}
}
[HttpGet("logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
[AllowAnonymous]
[HttpGet("denied")]
public IActionResult Denied()
{
return View();
}
}

}
东莞网站建设www.zg886.cn

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: