asp.net core策略授权

首先看基于角色组,或用户名,或基于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
{
//无权限跳转到拒绝页面
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值