拦截asp.net核心授权操作以在成功授权后执行自定义操作

我的网络应用控制器上有[授权]属性,因此任何端点命中都会确保用户首先被重定向到登录OAuth服务器(如果尚未登录)。

我现在想要在用户每次登录时开始将用户声明写入Web应用程序数据库。为此,我需要在每次用户成功登录/授权时在Web应用程序上运行一些代码。

我得到了一个线索,它涉及添加自定义中间件。

我的启动ConfigureServices代码目前如下:

public class Startup { public Startup(IConfiguration configuration, IHostingEnvironment env) { Configuration = configuration; Env = env; } public IHostingEnvironment Env { get; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Adds a default in-memory implementation of IDistributedCache. services.AddDistributedMemoryCache(); services.AddSession(options => { options.Cookie.HttpOnly = true; }); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.SignInScheme = "Cookies"; options.Authority = Configuration["auth:oidc:authority"]; options.RequireHttpsMetadata = !Env.IsDevelopment(); options.ClientId = Configuration["auth:oidc:clientid"]; options.ClientSecret = Configuration["auth:oidc:clientsecret"]; options.ResponseType = "code id_token"; options.Scope.Add(Configuration["auth:oidc:clientid"]); options.Scope.Add("offline_access"); options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; }); } ... [] 

所以我的问题是:我需要添加哪些代码,以及在何处调用将包含自定义操作的方法?

OpenIDConnectOptions类具有Events属性,适用于此类场景。 此Events属性( OpenIdConnectEvents )具有OnTokenValidated属性( Func ),您可以覆盖该属性,以便在令牌得到validation时得到通知。 这是一些代码:

 options.Events.OnTokenValidated = ctx => { // Your code here. return Task.CompletedTask; }; 

在示例代码中, ctxTokenValidatedContext ,它最终包含Principal属性( ClaimsPrincipal ):您应该能够使用此属性来获取所需的声明等,例如ctx.Principal.FindFirst(...)

正如@Brad在评论中提到的那样,为每个请求调用OnTokenValidated并且(根据您自己的注释)将不包含您需要的UserInfo。 为了实现这一点,您可以使用OnUserInformationReceived ,如下所示:

 options.Events.OnUserInformationReceived = ctx => { // Here, ctx.User is a JObject that should include the UserInfo you need. return Task.CompletedTask; }; 

这个例子中的ctx是一个UserInformationReceivedContext :它仍然包含Principal属性,但也有一个User属性( JObject ),正如我在代码中用注释调用的那样。

您应该查看OpenIdConnectOptions.Events 。 我没有示例,但这是挂钩OIDC中间件的地方。