拦截 asp.net 核心授权操作,授权成功后执行自定义操作
Intercept asp.net core Authorize action to perform custom action upon successful authorization
我的 Web 应用程序控制器上有一个 [Authorize] 属性,因此任何端点命中都会确保用户被重定向到首先登录 OAuth 服务器(如果尚未登录。)
我现在想在每次用户登录时开始将用户声明写入 Web 应用程序数据库。为此,我需要在每次用户成功登录/授权时在 Web 应用程序上运行一些代码.
我得到的线索是它涉及添加自定义中间件。
我的Startup 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
class has an Events
property, that is intended for scenarios like this. This Events
property (OpenIdConnectEvents
) has an OnTokenValidated
属性 (Func<TokenValidatedContext, Task>
),您可以覆盖它以便在验证令牌时收到通知。这是一些代码:
options.Events.OnTokenValidated = ctx =>
{
// Your code here.
return Task.CompletedTask;
};
在示例代码中,ctx
是一个TokenValidatedContext
, which ultimately包含一个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
),正如我在代码中用注释指出的那样。
我的 Web 应用程序控制器上有一个 [Authorize] 属性,因此任何端点命中都会确保用户被重定向到首先登录 OAuth 服务器(如果尚未登录。)
我现在想在每次用户登录时开始将用户声明写入 Web 应用程序数据库。为此,我需要在每次用户成功登录/授权时在 Web 应用程序上运行一些代码.
我得到的线索是它涉及添加自定义中间件。
我的Startup 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
class has an Events
property, that is intended for scenarios like this. This Events
property (OpenIdConnectEvents
) has an OnTokenValidated
属性 (Func<TokenValidatedContext, Task>
),您可以覆盖它以便在验证令牌时收到通知。这是一些代码:
options.Events.OnTokenValidated = ctx =>
{
// Your code here.
return Task.CompletedTask;
};
在示例代码中,ctx
是一个TokenValidatedContext
, which ultimately包含一个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
),正如我在代码中用注释指出的那样。