IAuthorizationFilter 不是每次都调用
IAuthorizationFilter not called every time
我们使用 IAuthorizationFilter
class 来过滤所有请求,并检查身份验证 cookie 中是否仍然存在自定义用户声明(多租户应用程序)。这些信息对于应用程序的其余部分是必不可少的。如果这些信息不存在,我们将重定向到登录页面。
public class TokenAuthorizationFilter : IAuthorizationFilter, IAsyncAuthorizationFilter
{
public TokenAuthorizationFilter()
{
// Some dependency injection ...
}
public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
{
CheckToken(context);
}
public Task OnAuthorizationAsync(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
{
return CheckToken(context);
}
}
然后我们像这样注册我们的过滤器
services.AddMvc(config =>
{
config.Filters.Add(typeof(TokenAuthorizationFilter));
});
而我想要访问的控制器的操作非常简单:
[Authorize(Policy = "TokenValid")]
public class HomeController : AjaxBaseController
{
public IActionResult Index()
{
return View();
}
}
我们甚至没有达到 AuthorizeAttribute
的政策。正如我在堆栈跟踪中看到的那样,Identity 在检查 CookieAuthenticationOptions
后试图在中间件的某处创建一个 Microsoft.AspNet.Identity.SignInManager
,我假设他正在尝试重新登录用户,但它没有检查我的过滤器?登录在我们的应用程序中非常特殊,所以我不想让 Identity 自动登录我们的用户。当身份验证 cookie 过期时,我可以重现此问题。
有任何想法吗 ?谢谢!
您还需要使 TokenAuthorizationFilter
继承自 AuthorizeAttribute
作为授权过滤器,并将其重命名为 TokenAuthorizationFilterAttribute
。
这将成为您可以使用 [TokenAuthorizationFilter]
:
调用的属性
[TokenAuthorizationFilter]
public class HomeController : AjaxBaseController
{
public IActionResult Index()
{
return View();
}
}
同时实现 IAuthorizationFilter 和 IAsyncAuthorizationFilter 时要小心,因为 ASP.NET Core 在这种情况下只会调用异步方法:如果您不需要任何异步调用,则只实现 IAuthorizationFilter 接口。
另外,如果你一直这样注册过滤器:
services.AddMvc(config =>
{
config.Filters.Add(typeof(TokenAuthorizationFilter));
});
您会注意到每个操作都会调用过滤器,因为它会强制每次都调用授权过滤器,因此在这种情况下您不需要在操作之上添加属性。
终于找到问题所在了。每隔 30 分钟,Identity 就会尝试通过 SecurityStamp
验证来验证用户,这导致应用程序崩溃,因为它需要一个在验证时不存在的数据库连接。我们通过重新实现 OnValidatePrincipal
:
在我们的启动中取消了这个验证
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents { OnValidatePrincipal = (context) => Task.FromResult(0) };
我们使用 IAuthorizationFilter
class 来过滤所有请求,并检查身份验证 cookie 中是否仍然存在自定义用户声明(多租户应用程序)。这些信息对于应用程序的其余部分是必不可少的。如果这些信息不存在,我们将重定向到登录页面。
public class TokenAuthorizationFilter : IAuthorizationFilter, IAsyncAuthorizationFilter
{
public TokenAuthorizationFilter()
{
// Some dependency injection ...
}
public void OnAuthorization(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
{
CheckToken(context);
}
public Task OnAuthorizationAsync(Microsoft.AspNet.Mvc.Filters.AuthorizationContext context)
{
return CheckToken(context);
}
}
然后我们像这样注册我们的过滤器
services.AddMvc(config =>
{
config.Filters.Add(typeof(TokenAuthorizationFilter));
});
而我想要访问的控制器的操作非常简单:
[Authorize(Policy = "TokenValid")]
public class HomeController : AjaxBaseController
{
public IActionResult Index()
{
return View();
}
}
我们甚至没有达到 AuthorizeAttribute
的政策。正如我在堆栈跟踪中看到的那样,Identity 在检查 CookieAuthenticationOptions
后试图在中间件的某处创建一个 Microsoft.AspNet.Identity.SignInManager
,我假设他正在尝试重新登录用户,但它没有检查我的过滤器?登录在我们的应用程序中非常特殊,所以我不想让 Identity 自动登录我们的用户。当身份验证 cookie 过期时,我可以重现此问题。
有任何想法吗 ?谢谢!
您还需要使 TokenAuthorizationFilter
继承自 AuthorizeAttribute
作为授权过滤器,并将其重命名为 TokenAuthorizationFilterAttribute
。
这将成为您可以使用 [TokenAuthorizationFilter]
:
[TokenAuthorizationFilter]
public class HomeController : AjaxBaseController
{
public IActionResult Index()
{
return View();
}
}
同时实现 IAuthorizationFilter 和 IAsyncAuthorizationFilter 时要小心,因为 ASP.NET Core 在这种情况下只会调用异步方法:如果您不需要任何异步调用,则只实现 IAuthorizationFilter 接口。
另外,如果你一直这样注册过滤器:
services.AddMvc(config =>
{
config.Filters.Add(typeof(TokenAuthorizationFilter));
});
您会注意到每个操作都会调用过滤器,因为它会强制每次都调用授权过滤器,因此在这种情况下您不需要在操作之上添加属性。
终于找到问题所在了。每隔 30 分钟,Identity 就会尝试通过 SecurityStamp
验证来验证用户,这导致应用程序崩溃,因为它需要一个在验证时不存在的数据库连接。我们通过重新实现 OnValidatePrincipal
:
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents { OnValidatePrincipal = (context) => Task.FromResult(0) };