【问题标题】:Intercept asp.net core Authorize action to perform custom action upon successful authorization拦截asp.net core Authorize action,授权成功后执行自定义动作
【发布时间】:2018-09-16 08:02:18
【问题描述】:

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

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

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

我的启动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;

            });

    }

... []

所以我的问题是:我需要添加什么代码,以及在哪里,才能调用包含我的自定义操作的方法?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-core identityserver4 asp.net-core-middleware


    【解决方案1】:

    OpenIDConnectOptions 类有一个 Events 属性,用于此类场景。这个Events 属性(OpenIdConnectEvents) 有一个OnTokenValidated 属性(Func<TokenValidatedContext, Task>),您可以覆盖它以便在验证令牌时收到通知。这是一些代码:

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

    在示例代码中,ctx 是一个TokenValidatedContext,其中ultimately 包含一个Principal 属性(ClaimsPrincipal):您应该能够使用此属性来获取您的声明等需要使用例如ctx.Principal.FindFirst(...).

    正如@Brad 在 cmets 中提到的,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),正如我在代码中用注释调用的那样。

    【讨论】:

    • OnUserInformationReceived 事件更适合 OP 的需求。它在成功登录时执行一次。您提供的事件会在每个请求上执行。
    • 如果您使用的是 Azure B2C,那么此答案显示了如何访问 OIDC 事件:stackoverflow.com/a/58515372/2608
    猜你喜欢
    • 2020-10-11
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    相关资源
    最近更新 更多