继续使用Cookie在Web API中使用OWIN和app.UseWebApi进行身份验证

时间:2016-05-07 11:52:44

标签: 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控制器中User始终为null。

这是我Startup.cs的代码:

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

控制器工作,路由也一样,使用相同的WebApiConfig.cs文件。但是,现在我的API控制器中的用户为空。 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))
    }
});    

2 个答案:

答案 0 :(得分:4)

  

我的HttpConfiguration实例中缺少什么   在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
}

同时查看 WebApiAppBuilderExtensions.cs

UseWebAPi扩展名的方式
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

  

对于标准IIS托管HttpConfiguration是   GlobalConfiguration.Configuration

     

对于自托管,HttpConfiguration是您的   HttpSelfHostConfiguration实例。

     

对于 OWIN集成HttpConfiguration是您创建的   你的app启动类并传递给Web API中间件。

使用标准的IIS托管,IIS处理用户身份验证和标识,它将为您插入HttpConfiguration和管道。当您new向上HttpConfiguration自我时,您没有IIS的优势来管理身份验证,因此User仍为null

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

看看这个问题:OWIN Cookie Authentication

答案显示,在WebApi配置中,以下行忽略了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的身份验证工作。

更新:

你表示......

  

控制器工作,路由也一样,使用相同的WebApiConfig.cs文件。   但是,我的API控制器中的User现在是null

看看......

<强> Combining Authentication Filters with Host-Level Authentication

  

“主机级认证”是主机执行的认证   (例如IIS),在请求到达Web API框架之前。

     

通常,您可能希望为其启用主机级身份验证   您的应用程序的其余部分,但为您的Web API控制器禁用它。   例如,典型的情况是启用表单身份验证   主机级别,但对Web API使用基于令牌的身份验证。

     

要在Web API管道中禁用主机级身份验证,请调用   您的配置中为config.SuppressHostPrincipal()这会导致   用于从进入的任何请求中删除IPrincipal的Web API   Web API管道。实际上,它“取消认证”请求。

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

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

如果在您的方案中,您的网络API配置中包含以下内容,则可以解释为什么User始终为null。我建议你将其评论或一起删除。

答案 1 :(得分:2)

当我从仅限WebApi的服务转移到OWIN时,我遇到了这个问题。我的用户即使经过正确的身份验证也是null。在我的情况下,我在拒绝默认主机身份验证后错过了添加HostAuthenticationFilter。

config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(YourAuthenticationType));

检查您是否忘记了身份验证过滤器。我使用Unity(而不是Autofac)成功完成了这项工作,但校长完全相同。在我的OWIN启动这个订单:

ConfigureAuth(app);
WebApiConfig.Register(httpConfiguration);
app.UseWebApi(httpConfiguration);