IdentityServer3自定义OWIN中间件以及其他MVC控制器

时间:2018-02-15 16:29:04

标签: c# asp.net-mvc owin identityserver3

我有一个Identity Server 3的实现,其中依赖于URL请求它可以为IDS提供不同的设置(配置的选项等)。

这样可以正常工作,但我在向应用程序添加MVC控制器/页面时遇到问题(如https://github.com/IdentityServer/IdentityServer3/issues/1140所述) - 当我尝试加载新页面时出现404异常。如果我将coreApp.Use<IdentityServerWithTenantSwitchingMiddleware>(coreApp.Properties);替换为coreApp.UseIdentityServer(new IdentityServerWithTenantSwitchingMiddleware(null, null).GetOptions());,它会按预期运行,我确定问题出现在我InvokeIdentityServerWithTenantSwitchingMiddleware的实施中。

在我看来好像我错过了一些告诉IDS我想要使用MVC控制器的bootstrap / setup。或者其他的东西。我已经看到了几个类似的问题/问题(https://github.com/IdentityServer/IdentityServer3/issues/1934),但没有一个与这个问题有关。

我使用GitHub中的IdentityServer3 CustomUserService({3}}(具体为see my fork of CustomUserService demoIdentityServerWithTenantSwitchingMiddleware.cs)重现了此问题。如果您登录演示(密码/用户名:alice),您可以看到此问题 - 它会尝试渲染eula页面时抛出异常。

我将在下面列出重要的代码:

Startup.cs

public void Configuration(IAppBuilder app)
{
    Log.Logger = new LoggerConfiguration()
                   .MinimumLevel.Debug()
                   .WriteTo.Trace()
                   .CreateLogger();

    app.Map("/core", coreApp =>
    {
         coreApp.Use<IdentityServerWithTenantSwitchingMiddleware>(coreApp.Properties);
    });
}

IdentityServerWithTenantSwitchingMiddleware

public override Task Invoke(IOwinContext context)
{
    var app = new AppBuilder();

    //Do some magic based on current request

    var options = GetOptions();

    _properties.ForEach(kvp =>
    {
        if (!app.Properties.ContainsKey(kvp.Key))
        {
            app.Properties.Add(kvp.Key, kvp.Value);
        }
    });

    app.UseIdentityServer(options);
     return app.Build()(context.Environment);
}

private IdentityServerOptions GetOptions()
{
    var factory = new IdentityServerServiceFactory()
        .UseInMemoryClients(Clients.Get())
        .UseInMemoryScopes(Scopes.Get());

    // different examples of custom user services
    var userService = new EulaAtLoginUserService();

    // note: for the sample this registration is a singletone (not what you want in production probably)
    factory.UserService = new Registration<IUserService>(resolver => userService);

    var options = new IdentityServerOptions
    {
        SiteName = "IdentityServer3 - CustomUserService",

        SigningCertificate = Certificate.Get(),
        Factory = factory,

        AuthenticationOptions = new AuthenticationOptions
        {
            LoginPageLinks = new LoginPageLink[] {
                    new LoginPageLink{
                        Text = "Register",
                        Href = "localregistration"
                    }
                }
        },

        EventsOptions = new EventsOptions
        {
            RaiseSuccessEvents = true,
            RaiseErrorEvents = true,
            RaiseFailureEvents = true,
            RaiseInformationEvents = true
        }
    };

    return options;
}

感谢任何/所有帮助/建议。

亚历

1 个答案:

答案 0 :(得分:0)

找到了我的问题的答案。

取自https://github.com/damianh/DynamicKatanaPipeline - 看起来好像我没有在管道中运行下一步。在这里使用代码,万一它可以帮助任何人:

public override Task Invoke(IOwinContext context)
{
    var app = ConfigurePipeline(context);
    var dynamicAppFunc = app.Build();
    return dynamicAppFunc(context.Environment);
}

private IAppBuilder ConfigurePipeline(IOwinContext context)
{
    var app = new AppBuilder();

    app.UseIdentityServer(GetOptions(context));

    app.Run(_next.Invoke);

    return app;
}