OnAuthorization 后自定义 AuthorizeAttribute 抛出错误
Custom AuthorizeAttribute throwing error after OnAuthorization
我想定制 AuthorizeAttribute
。我想使用 IMemoryCache
来存储令牌,并且我正在使用自定义提供程序来注入 IMemoryCache 实例。我的问题是在 OnAuthorization
方法之后,它没有被称为我的控制器的操作,它抛出了一个我无法捕获的内部服务器错误。
这是到目前为止的实现
public class ApiAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public IMemoryCache Cache { get; set; }
/// <summary>
/// Verifica se o token é válido na sessão
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public void OnAuthorization(AuthorizationFilterContext context)
{
//Check we have a valid HttpContext
if (context.HttpContext == null)
throw new ArgumentNullException("httpContext");
string token;
token = context.HttpContext.Request.QueryString.Value;
if (String.IsNullOrEmpty(token))
token = context.HttpContext.Request.Form["token"];
if (String.IsNullOrEmpty(token))
{
context.Result = new UnauthorizedResult();
return;
}
if (Cache == null)
{
context.Result = new UnauthorizedResult();
return;
}
if (token.Contains("="))
{
token = token.Split('=')[1];
}
var tokens = Cache.Get<Dictionary<string, User>>("tokens");
var result = (from t in tokens where t.Key == token select t.Value).ToList();
var controller = (string)context.RouteData.Values["controller"];
var action = (string)context.RouteData.Values["action"];
if (result.Count < 1)
context.Result = new UnauthorizedResult();
}
}
public class CacheProvider : IApplicationModelProvider
{
private IMemoryCache _cache;
public CacheProvider(IMemoryCache cache)
{
_cache = cache;
}
public int Order { get { return -1000 + 10; } }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
foreach (var controllerModel in context.Result.Controllers)
{
// pass the depencency to controller attibutes
controllerModel.Attributes
.OfType<ApiAuthorizeAttribute>().ToList()
.ForEach(a => a.Cache = _cache);
// pass the dependency to action attributes
controllerModel.Actions.SelectMany(a => a.Attributes)
.OfType<ApiAuthorizeAttribute>().ToList()
.ForEach(a => a.Cache = _cache);
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
// intentionally empty
}
}
这是控制器
[ApiAuthorize]
[HttpPost]
public JsonResult Delete([FromForm] string inputId)
{
//Do stuff
}
提前致谢
经过一番挖掘,我发现了这种方法,我不知道这是否是实现该目标的最佳方法
我创建了策略要求
public class TokenRequirement : IAuthorizationRequirement
{
}
还有一个AuthorizationHandler
public class TokenRequirementHandler : AuthorizationHandler<TokenRequirement>
{
public IMemoryCache Cache { get; set; }
public TokenRequirementHandler(IMemoryCache memoryCache)
{
Cache = memoryCache;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenRequirement requirement)
{
return Task.Run(() => { //access the cache and then
context.Succeed(requirement); });
}
}
在启动时,我注册了处理程序并添加了授权
services.AddAuthorization(options =>
{
options.AddPolicy("Token",
policy => policy.Requirements.Add(new Authorize.TokenRequirement()));
});
services.AddSingleton<IAuthorizationHandler, Authorize.TokenRequirementHandler>();
在控制器中我使用了 Authorize
属性
[Authorize(Policy = "Token")]
[HttpPost]
public JsonResult Delete([FromForm] string inputId)
{
//Do stuff
}
现在可以了。
谢谢。
我想定制 AuthorizeAttribute
。我想使用 IMemoryCache
来存储令牌,并且我正在使用自定义提供程序来注入 IMemoryCache 实例。我的问题是在 OnAuthorization
方法之后,它没有被称为我的控制器的操作,它抛出了一个我无法捕获的内部服务器错误。
这是到目前为止的实现
public class ApiAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public IMemoryCache Cache { get; set; }
/// <summary>
/// Verifica se o token é válido na sessão
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public void OnAuthorization(AuthorizationFilterContext context)
{
//Check we have a valid HttpContext
if (context.HttpContext == null)
throw new ArgumentNullException("httpContext");
string token;
token = context.HttpContext.Request.QueryString.Value;
if (String.IsNullOrEmpty(token))
token = context.HttpContext.Request.Form["token"];
if (String.IsNullOrEmpty(token))
{
context.Result = new UnauthorizedResult();
return;
}
if (Cache == null)
{
context.Result = new UnauthorizedResult();
return;
}
if (token.Contains("="))
{
token = token.Split('=')[1];
}
var tokens = Cache.Get<Dictionary<string, User>>("tokens");
var result = (from t in tokens where t.Key == token select t.Value).ToList();
var controller = (string)context.RouteData.Values["controller"];
var action = (string)context.RouteData.Values["action"];
if (result.Count < 1)
context.Result = new UnauthorizedResult();
}
}
public class CacheProvider : IApplicationModelProvider
{
private IMemoryCache _cache;
public CacheProvider(IMemoryCache cache)
{
_cache = cache;
}
public int Order { get { return -1000 + 10; } }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
foreach (var controllerModel in context.Result.Controllers)
{
// pass the depencency to controller attibutes
controllerModel.Attributes
.OfType<ApiAuthorizeAttribute>().ToList()
.ForEach(a => a.Cache = _cache);
// pass the dependency to action attributes
controllerModel.Actions.SelectMany(a => a.Attributes)
.OfType<ApiAuthorizeAttribute>().ToList()
.ForEach(a => a.Cache = _cache);
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
// intentionally empty
}
}
这是控制器
[ApiAuthorize]
[HttpPost]
public JsonResult Delete([FromForm] string inputId)
{
//Do stuff
}
提前致谢
经过一番挖掘,我发现了这种方法,我不知道这是否是实现该目标的最佳方法
我创建了策略要求
public class TokenRequirement : IAuthorizationRequirement
{
}
还有一个AuthorizationHandler
public class TokenRequirementHandler : AuthorizationHandler<TokenRequirement>
{
public IMemoryCache Cache { get; set; }
public TokenRequirementHandler(IMemoryCache memoryCache)
{
Cache = memoryCache;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenRequirement requirement)
{
return Task.Run(() => { //access the cache and then
context.Succeed(requirement); });
}
}
在启动时,我注册了处理程序并添加了授权
services.AddAuthorization(options =>
{
options.AddPolicy("Token",
policy => policy.Requirements.Add(new Authorize.TokenRequirement()));
});
services.AddSingleton<IAuthorizationHandler, Authorize.TokenRequirementHandler>();
在控制器中我使用了 Authorize
属性
[Authorize(Policy = "Token")]
[HttpPost]
public JsonResult Delete([FromForm] string inputId)
{
//Do stuff
}
现在可以了。 谢谢。