授权取决于动作名用户 [英] Authorizing a user depending on the action name
问题描述
我有很多很多的动作控制器。每个动作都有它自己的角色(角色名称= ControllerName.actionName)。
I have many controllers with many actions. Each action has it's own Role ( Role name = ControllerName.actionName ).
在previous版本我可以测试当前用户是否可以存取权限的操作或不使用通用AuthorizeAttribute:
In previous versions I could test if the current user can acces an action or not using a "generic" AuthorizeAttribute :
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string currentAction = actionContext.ActionDescriptor.ActionName;
string currentController = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
Roles = (currentController + "." + currentAction).ToLower();
base.OnAuthorization(actionContext);
}
随着版本的asp.net 5,我发现我需要使用要求(<一个href=\"http://stackoverflow.com/questions/31464359/custom-authorizeattribute-in-asp-net-5-mvc-6\">custom AuthorizeAttribute在ASP.NET MVC 5 6 )。问题是,AuthorizationContext不能给我们介绍一下该用户试图去操作的信息。
With the version asp.net 5, I've found that I need to use requirements ( custom AuthorizeAttribute in ASP.NET 5 MVC 6 ). The problem is that the AuthorizationContext does not give us the information about the action that the user is trying to get to.
我不想把一个授权上的每个动作的属性,有没有什么办法来实现我的新框架的要求? (ⅠpreFER避免使用HttpContext.Current,它不会在一个流水线结构合身)
I don't want to put an Authorize attribute on each action, is there any way to achieve my requirement with the new framework ? ( I prefer to avoid using HttpContext.Current, it doesn't fit well in a pipeline architecture )
推荐答案
下面是执行自定义验证的一般过程。您的情况可能能够在第一步中完全解决,因为你可以为装饰你的
Here is the general process for enforcing custom authentication. Your situation may be able to solved completely in step one, since you could add a Claim for the Role that decorates your
1。的身份验证的通过为用户创造一个身份
1. authenticate by creating an identity for the user
写作中间件,并通过 IApplicationBuilder.UseMiddleware&LT其插入到管道;&GT;
是如何认证的定制完成。这是我们提取任何信息可能以后需要进行授权,并把它变成一个 ClaimsIdentity
。我们有一个的HttpContext
这里,所以我们可以从标题,饼干,请求路径等。这里抢信息是一个例子:
Writing middleware and inserting it into the pipeline via IApplicationBuilder.UseMiddleware<>
is how custom authentication is done. This is where we extract whatever info may be later needed for authorization, and put it into an ClaimsIdentity
. We have an HttpContext
here so we can grab info from the header, cookies, requested path, etc. Here is an example:
public class MyAuthHandler : AuthenticationHandler<MyAuthOptions>
{
protected override Task<AuthenticationTicket> HandleAuthenticateAsync()
{
// grab stuff from the HttpContext
string authHeader = Request.Headers["Authorization"] ?? "";
string path = Request.Path.ToString() ?? "";
// make a MyAuth identity with claims specifying what we'll validate against
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Authentication, authHeader),
new Claim(ClaimTypes.Uri, path)
}, Options.AuthenticationScheme);
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity),
new AuthenticationProperties(), Options.AuthenticationScheme);
return Task.FromResult(ticket);
}
}
public class MyAuthOptions : AuthenticationOptions
{
public const string Scheme = "MyAuth";
public MyAuthOptions()
{
AuthenticationScheme = Scheme;
AutomaticAuthentication = true;
}
}
public class MyAuthMiddleware : AuthenticationMiddleware<MyAuthOptions>
{
public MyAuthMiddleware(
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
IUrlEncoder urlEncoder,
IOptions<MyAuthOptions> options,
ConfigureOptions<MyAuthOptions> configureOptions)
: base(next, options, loggerFactory, urlEncoder, configureOptions)
{
}
protected override AuthenticationHandler<MyAuthOptions> CreateHandler()
{
return new MyAuthHandler();
}
}
public static class MyAuthMiddlewareAppBuilderExtensions
{
public static IApplicationBuilder UseMyAuthAuthentication(this IApplicationBuilder app, string optionsName = "")
{
return app.UseMiddleware<MyAuthMiddleware>(
new ConfigureOptions<MyAuthOptions>(o => new MyAuthOptions()) { Name = optionsName });
}
}
要使用这个中间件 Startup.Configure
插入此路由之前: app.UseMyAuthAuthentication();
To use this middleware insert this in Startup.Configure
prior to the routing: app.UseMyAuthAuthentication();
2。的授权的通过身份强制要求
2. authorize by enforcing requirements on the identity
我们已经为用户的身份,但我们仍然需要强制执行。要做到这一点,我们需要编写一个 AuthorizationHandler
是这样的:
We've created an identity for the user but we still need to enforce it. To do this we need to write an AuthorizationHandler
like this:
public class MyAuthRequirement : AuthorizationHandler<MyAuthRequirement>, IAuthorizationRequirement
{
public override void Handle(AuthorizationContext context, MyAuthRequirement requirement)
{
// grab the identity for the MyAuth authentication
var myAuthIdentities = context.User.Identities
.Where(x => x.AuthenticationType == MyAuthOptions.Scheme).FirstOrDefault();
if (myAuthIdentities == null)
{
context.Fail();
return;
}
// grab the authentication header and uri types for our identity
var authHeaderClaim = myAuthIdentities.Claims.Where(x => x.Type == ClaimTypes.Authentication).FirstOrDefault();
var uriClaim = context.User.Claims.Where(x => x.Type == ClaimTypes.Uri).FirstOrDefault();
if (uriClaim == null || authHeaderClaim == null)
{
context.Fail();
return;
}
// enforce our requirement (evaluate values from the identity/claims)
if ( /* passes our enforcement test */ )
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
}
}
3。添加的要求处理程序授权策略
我们的认证要求仍然需要被添加到 Startup.ConfigureServices
这样它可用于:
Our authentication requirement still needs to be added to the Startup.ConfigureServices
so that it can be used:
// add our policy to the authorization configuration
services.ConfigureAuthorization(auth =>
{
auth.AddPolicy(MyAuthOptions.Scheme,
policy => policy.Requirements.Add(new MyAuthRequirement()));
});
4。使用授权策略
最后一步是通过装饰我们的行动或控制器强制执行的具体行动这一要求[授权(MyAuth)]
。如果我们有很多控制器,每个控制器有许多动作需要执行,那么我们可能想使一个基类,只是装饰的单控制器。
The final step is to enforce this requirement for specific actions by decorating our action or controller with [Authorize("MyAuth")]
. If we have many controllers, each with many action which require enforcement, then we may want to make a base class and just decorate that single controller.
您的简单情况:
每个动作都有它自己的角色(角色名称= ControllerName.actionName>)
Each action has it's own Role ( Role name = ControllerName.actionName> )
如果你已经有了自己的行为作出微调 [授权(角色=controllername.actionname)]
,那么你可能只需要上述部分#1。只需添加一个新的索赔(ClaimTypes.Rolecontrollername.actionname)
有效期为特定的要求。
If you already have all your actions fine-tuned with [Authorize(Roles = "controllername.actionname")]
then you probably only need part #1 above. Just add a new Claim(ClaimTypes.Role, "controllername.actionname")
that is valid for the particular request.
这篇关于授权取决于动作名用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!