asp.net-mvc - 使用 OWIN 和 app.UseWebApi 在 Web API 中继续使用 cookie 进行身份验证

标签 asp.net-mvc asp.net-web-api2 owin

我想继续在我的应用程序的 MVC 和 API 部分中使用相同的 cookie。我知道这不是很安全,但仍然如此。
如果我在 VS 中创建一个新的 MVC 项目,一切正常,Web API 是使用 GlobalConfiguration.Configure(WebApiConfig.Register) 从 Global.asax 设置的.
但是,一旦我尝试使用 OWIN 来配置 Web API,我就会遇到一个问题,即我的 API Controller 中的用户始终为空。

这是我来自 Startup.cs 的代码:

var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);

Controller 工作,路由也一样,使用相同的 WebApiConfig.cs 文件。但是,现在我的 API Controller 中的 User 为空。我的 HttpConfiguration 实例中缺少什么存在于 GlobalConfiguration.Configuration ?

我需要使用我自己的 HttpConfiguration 实例而不是使用 GlobalConfiguration.Configuration因为我打算使用 Autofac 而它不适用于 GlobalConfiguration如前所述 here

编辑:

我的 Startup.Auth.cs :
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        // Enables the application to validate the security stamp when the user logs in.
        // This is a security feature which is used when you change a password or add an external login to your account.  
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});    

最佳答案

What's missing from my instance of HttpConfiguration that is present in GlobalConfiguration.Configuration?



GlobalConfiguration.cs Source code from Codeplex

创建新 HttpConfiguration 时的主要区别和一个在 GlobalConfiguration ...
public static class GlobalConfiguration
{
    private static Lazy<HttpConfiguration> _configuration = CreateConfiguration();

    //...other code removed for brevity

    /// <summary>
    /// Gets the global <see cref="T:System.Web.Http.HttpConfiguration"/>.
    /// </summary>
    public static HttpConfiguration Configuration
    {
        get { return _configuration.Value; }
    }

    //...other code removed for brevity

    private static Lazy<HttpConfiguration> CreateConfiguration()
    {
        return new Lazy<HttpConfiguration>(() =>
        {
            HttpConfiguration config = new HttpConfiguration(new HostedHttpRouteCollection(RouteTable.Routes));
            ServicesContainer services = config.Services;
            Contract.Assert(services != null);
            services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver());
            services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver());
            services.Replace(typeof(IHostBufferPolicySelector), new WebHostBufferPolicySelector());
            services.Replace(typeof(IExceptionHandler),
                new WebHostExceptionHandler(services.GetExceptionHandler()));
            return config;
        });
    }

    //...other code removed for brevity
}

另外在看时如何UseWebAPi分机在 WebApiAppBuilderExtensions.cs
public static IAppBuilder UseWebApi(this IAppBuilder builder, HttpConfiguration configuration)
{
    if (builder == null)
    {
        throw new ArgumentNullException("builder");
    }

    if (configuration == null)
    {
        throw new ArgumentNullException("configuration");
    }

    HttpServer server = new HttpServer(configuration);

    try
    {
        HttpMessageHandlerOptions options = CreateOptions(builder, server, configuration);
        return UseMessageHandler(builder, options);
    }
    catch
    {
        server.Dispose();
        throw;
    }
}

...配置包含在自己的 HttpServer 中它覆盖了 GlobalConfiguration 使用的默认值.

查看您包含的文档,我最终遇到了 this

For standard IIS hosting, the HttpConfiguration is GlobalConfiguration.Configuration.

For self hosting, the HttpConfiguration is your HttpSelfHostConfiguration instance.

For OWIN integration, the HttpConfiguration is the one you create in your app startup class and pass to the Web API middleware.



使用标准的 IIS 托管,IIS 处理插入到 HttpConfiguration 中的用户身份验证和标识。和引擎盖下的管道。当您new向上 HttpConfiguration您自己没有 IIS 为您管理身份验证的好处,因此您的 User遗体 null .

从您的帖子中,您表明您使用了多个 HttpConfiguration 实例。看起来您正在尝试混合使用 IIS 和 OWIN。

看着这个问题:OWIN Cookie Authentication

答案表明,在 WebApi Config 中,以下行忽略了 cookie。
// Configure Web API to use only bearer token authentication.
// If you don't want the OWIN authentication to flow to your Web API then call 
// SuppressDefaultHostAuthentication on your HttpConfiguration. 
// This blocks all host level authentication at that point in the pipeline.
config.SuppressDefaultHostAuthentication();

注释掉它使基于 cookie 的身份验证工作。

更新:

你指出...

Controllers work, routes too, same WebApiConfig.cs file is used. However the User is null in my API controllers now



看一眼...

Combining Authentication Filters with Host-Level Authentication

“Host-level authentication” is authentication performed by the host (such as IIS), before the request reaches the Web API framework.

Often, you may want to to enable host-level authentication for the rest of your application, but disable it for your Web API controllers. For example, a typical scenario is to enable Forms Authentication at the host level, but use token-based authentication for Web API.

To disable host-level authentication inside the Web API pipeline, call config.SuppressHostPrincipal() in your configuration. This causes Web API to remove the IPrincipal from any request that enters the Web API pipeline. Effectively, it "un-authenticates" the request.


public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SuppressHostPrincipal();

        // Other configuration code not shown...
    }
}

如果在您的场景中,您的 web api 配置中有以下内容,这将解释为什么您的 User总是 null .我建议您将其注释掉或将其全部删除。

关于asp.net-mvc - 使用 OWIN 和 app.UseWebApi 在 Web API 中继续使用 cookie 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37088180/

相关文章:

asp.net-mvc - 在构建和发布时将文件添加到 bin 目录

c# - 如何防止创建处理同一请求的多个后台进程?

c# - 如何解析 OWIN 主机下文件的虚拟路径?

c# - 结构图 - 在运行时用模拟对象替换接口(interface)

asp.net-mvc - MVC 3 : May I place the controllers in a dll?

c# - 将 Ext.data.Store 中的 jsondata 转换为列表对象

asp.net-mvc - 使用超链接而不是按钮提交表单

Java Multipart POST 从 Web Api 服务器返回不支持的 MediaType

c# - 如何针对仅支持 SSL 的 Web Api Controller 对请求进行单元测试?

c# - 自动重定向未经身份验证的用户