IAuthorizationPolicyProvider:我可以使用多个策略提供者,还是必须在一个通用策略提供者中考虑所有情况?
IAuthorizationPolicyProvider: can I use multiple policy providers or I have to consider all cases inside one general policy provider?
在我的程序中我想
- 检查用户是否在特定用户table中注册所有可能的操作。
- 只是为了某些操作,我还想检查用户是否有适当的 CRUD 权限。
我使用以下代码检查 startup
中的 第一个条件 :
services.AddAuthorization(options =>
{
// This policy checks if a user is registered in our Users table.
options.AddPolicy(
"UserIsRegistered",
new AuthorizationPolicyBuilder()
.AddRequirements(new RegistrationRequirement())
.Build());
});
我也加
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization("UserIsRegistered");
});
我相应地定义了 RegistrationRequirement
和 RegistrationAuthorizationHandler
。
对于 第二个条件 ,我创建了一个属性 CrudAuthorizeAttribute
及其 CrudAuthorizationHandler
。由于我对每个可能的 Crud 操作都有不同的警察,因此我创建了一个 CrudPolicyProvider
.
然后我在Startup
中注册了所有内容:
services.AddTransient<IAuthorizationHandler, RegistrationAuthorizationHandler>();
services.AddTransient<IAuthorizationHandler, CrudAuthorizationHandler>();
services.AddTransient<IAuthorizationPolicyProvider, CrudPolicyProvider>();
现在我看到当我检查第一个条件时,我从 CrudPolicyProvider
获取策略,但我希望此策略生成器仅在第二个条件下提供策略。
因此:
- 有什么方法可以指定
CrudPolicyProvider
只能与 CrudAttribute
一起使用,不能用于其他地方吗?
- 更一般地说,我可以定义两个策略提供者(就像我可以用
IAuthorizationHandler
做的那样)
services.AddTransient<IAuthorizationPolicyProvider, FirstPolicyProvider>();
services.AddTransient<IAuthorizationPolicyProvider, SecondPolicyProvider>();
并且只在需要时使用每一个?
- 如果答案是 否,这是否意味着我必须定义一个
GeneralPolicyProvider
并在该提供商内部检查我每次必须提供哪些政策取决于关于我的情况? (类似于使用 POLICY_PREFIX
here?)。
谢谢!
can I define two policy providers (as I can do with IAuthorizationHandler)and use each one only when required
你可以。但是两个分离的策略提供者不会被相应地激活。您可能有多个策略提供者,但只会同时使用其中一个。使用 IAuthorizationPolicyProvider
时也没有魔法。
define a single GeneralPolicyProvider .... check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).
是的。但是您不必在任何地方都使用 Policy_Prefix。那样你会重复很多次。
更好的方法是在GeneralPolicyProvider
中注入一个IHttpContextAccessor
服务,这样你就可以在运行-查看当前的EndPoint
/HttpContext
-时间,然后您可以动态解析目标策略提供程序。
一个实现看起来像:
public class GenericPolicyProvider : IAuthorizationPolicyProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private AuthorizationOptions _authZOpts { get; }
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
private IAuthorizationPolicyProvider _fstPolicyProvider {get;set;}
private IAuthorizationPolicyProvider _sndPolicyProvider {get;set;}
public GenericPolicyProvider(IHttpContextAccessor httpContextAccessor, IOptions<AuthorizationOptions> options)
{
this._httpContextAccessor = httpContextAccessor;
this._authZOpts = options.Value;
this.FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
this._fstPolicyProvider = new FirstPolicyProvider(options.Value);
this._sndPolicyProvider = new SecondPolicyProvider(options.Value);
}
// use the target provider to provide policy
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
var targetPolicyProvider = this.GetPolicyProvider(policyName);
return targetPolicyProvider.GetPolicyAsync(policyName);
}
// get the target provider dynamically
private IAuthorizationPolicyProvider GetPolicyProvider(string policyName)
{
var httpContext = this._httpContextAccessor.HttpContext;
if(httpContext==null) throw new Exception("HttpContext must not be null");
// now you get the HttpContext
// check HttpContext to determine which policy provider should be used
// ...
// or check endpoint,e.g. get a mark filter by endpoint.Metadata.GetMetadata<...>()
var endpoint = httpContext.GetEndpoint();
var someMarker = endpoint.Metadata.GetMetadata<SomeMarker>();
// in short, resolve the policy provider dynamically:
if(shouldUseFirstPolicyProvider())
return this._fstPolicyProvider;
else if(shouldUseSecondPolicyProvider())
return this._sndPolicyProvider;
else
return this.FallbackPolicyProvider;
}
...
}
最后,别忘了在Startup中注册这个GenericPolicyProvider。
在我的程序中我想
- 检查用户是否在特定用户table中注册所有可能的操作。
- 只是为了某些操作,我还想检查用户是否有适当的 CRUD 权限。
我使用以下代码检查 startup
中的 第一个条件 :
services.AddAuthorization(options =>
{
// This policy checks if a user is registered in our Users table.
options.AddPolicy(
"UserIsRegistered",
new AuthorizationPolicyBuilder()
.AddRequirements(new RegistrationRequirement())
.Build());
});
我也加
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization("UserIsRegistered");
});
我相应地定义了 RegistrationRequirement
和 RegistrationAuthorizationHandler
。
对于 第二个条件 ,我创建了一个属性 CrudAuthorizeAttribute
及其 CrudAuthorizationHandler
。由于我对每个可能的 Crud 操作都有不同的警察,因此我创建了一个 CrudPolicyProvider
.
然后我在Startup
中注册了所有内容:
services.AddTransient<IAuthorizationHandler, RegistrationAuthorizationHandler>();
services.AddTransient<IAuthorizationHandler, CrudAuthorizationHandler>();
services.AddTransient<IAuthorizationPolicyProvider, CrudPolicyProvider>();
现在我看到当我检查第一个条件时,我从 CrudPolicyProvider
获取策略,但我希望此策略生成器仅在第二个条件下提供策略。
因此:
- 有什么方法可以指定
CrudPolicyProvider
只能与CrudAttribute
一起使用,不能用于其他地方吗? - 更一般地说,我可以定义两个策略提供者(就像我可以用
IAuthorizationHandler
做的那样)
services.AddTransient<IAuthorizationPolicyProvider, FirstPolicyProvider>();
services.AddTransient<IAuthorizationPolicyProvider, SecondPolicyProvider>();
并且只在需要时使用每一个?
- 如果答案是 否,这是否意味着我必须定义一个
GeneralPolicyProvider
并在该提供商内部检查我每次必须提供哪些政策取决于关于我的情况? (类似于使用POLICY_PREFIX
here?)。
谢谢!
can I define two policy providers (as I can do with IAuthorizationHandler)and use each one only when required
你可以。但是两个分离的策略提供者不会被相应地激活。您可能有多个策略提供者,但只会同时使用其中一个。使用 IAuthorizationPolicyProvider
时也没有魔法。
define a single GeneralPolicyProvider .... check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).
是的。但是您不必在任何地方都使用 Policy_Prefix。那样你会重复很多次。
更好的方法是在GeneralPolicyProvider
中注入一个IHttpContextAccessor
服务,这样你就可以在运行-查看当前的EndPoint
/HttpContext
-时间,然后您可以动态解析目标策略提供程序。
一个实现看起来像:
public class GenericPolicyProvider : IAuthorizationPolicyProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private AuthorizationOptions _authZOpts { get; }
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
private IAuthorizationPolicyProvider _fstPolicyProvider {get;set;}
private IAuthorizationPolicyProvider _sndPolicyProvider {get;set;}
public GenericPolicyProvider(IHttpContextAccessor httpContextAccessor, IOptions<AuthorizationOptions> options)
{
this._httpContextAccessor = httpContextAccessor;
this._authZOpts = options.Value;
this.FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
this._fstPolicyProvider = new FirstPolicyProvider(options.Value);
this._sndPolicyProvider = new SecondPolicyProvider(options.Value);
}
// use the target provider to provide policy
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
var targetPolicyProvider = this.GetPolicyProvider(policyName);
return targetPolicyProvider.GetPolicyAsync(policyName);
}
// get the target provider dynamically
private IAuthorizationPolicyProvider GetPolicyProvider(string policyName)
{
var httpContext = this._httpContextAccessor.HttpContext;
if(httpContext==null) throw new Exception("HttpContext must not be null");
// now you get the HttpContext
// check HttpContext to determine which policy provider should be used
// ...
// or check endpoint,e.g. get a mark filter by endpoint.Metadata.GetMetadata<...>()
var endpoint = httpContext.GetEndpoint();
var someMarker = endpoint.Metadata.GetMetadata<SomeMarker>();
// in short, resolve the policy provider dynamically:
if(shouldUseFirstPolicyProvider())
return this._fstPolicyProvider;
else if(shouldUseSecondPolicyProvider())
return this._sndPolicyProvider;
else
return this.FallbackPolicyProvider;
}
...
}
最后,别忘了在Startup中注册这个GenericPolicyProvider。