【问题标题】:Request.IsAuthenticated when using Identity with Owin for MVC and WebAPIRequest.IsAuthenticated 将 Identity 与 Owin 一起用于 MVC 和 WebAPI
【发布时间】:2014-05-15 13:54:28
【问题描述】:

我有一个 ASP.Net WebAPI 2.1,我刚刚过渡到使用不记名令牌使用 Identity 2.0。这工作正常。现在我试图引入一些 MVC 代码来创建一组登录和用户管理页面。我的问题是,当我将 WebApi HttpConfiguration设置为 SuppressDefaultHostAuthentication 时,我似乎无法让 Request.IsAuthenticated 从我的 Razor 视图中工作。

下面是我的代码,我不知道如何让它适用于这两种情况:(

这是我的Startup.cs,它设置了 Identity OWIN 模块和 WebAPI:

public class Startup
{
    public void Configure(IAppBuilder app)
    {
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/account/externalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
        };
        app.UseOAuthBearerTokens(OAuthOptions);

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie))
            }
        });

        var httpConfiguration = new HttpConfiguration();
        // Disable this line to allow Request.IsAuthenticated to work
        // But by doing this, it allows the 'redirect' to kick in on unauthenticated API requests, which returns a HTML page for a webapi call, rather than the JSON 'unauthenticated' response
        httpConfiguration.SuppressDefaultHostAuthentication();
        httpConfiguration.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie));
        httpConfiguration.MapHttpAttributeRoutes();
        app.UseWebApi(httpConfiguration);
    }
}

这是我的Global.asax.cs,它设置了 MVC 方面(AFAIK OWIN 不支持任何形式的app.UseMvc()):

public class WebApiApplication : HttpApplication
{
    protected void Application_Start()
    {
        // pretty much the defaults here for everything, just renamed
        AreaRegistration.RegisterAllAreas();
        MvcConfig.ConfigureFilters(GlobalFilters.Filters);
        MvcConfig.ConfigureRoutes(RouteTable.Routes);
        MvcConfig.ConfigureBundles(BundleTable.Bundles);
    }
}

现在,在我的 Razor 视图中,我想使用身份示例中使用的 Request.IsAuthenticated,但在启用 httpConfiguration.SuppressDefaultHostAuthentication 时会失败。我了解此扩展的目标是在身份中间件运行后删除当前身份 - 以便 WebAPI 身份验证过滤器可以随心所欲。但我希望在 MVC 方面,抑制不会发生。

Razor 视图示例:

@if (Request.IsAuthenticated) // false when using httpConfiguration.SuppressDefaultHostAuthentication
{
  <div>User.Identity.Email</div>
}

谁能帮帮我?这甚至可能吗?

谢谢!

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api owin asp.net-identity-2


    【解决方案1】:

    看起来这完全取决于应用程序构建器的顺序。如果我将身份承载配置放在 WebAPI 之前,那么我的 WebAPI 请求仍然使用身份 OWIN 模块。通过将 Cookie 配置放在 WebAPI 配置之后,Cookie 身份解析发生在 WebAPI 身份移除之后,MVC 执行之前。

    不确定这是否是“正确”的做法,但它似乎解决了我打开的所有测试用例。

    public class Startup
    {
        public void Configure(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/account/externalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
            };
            app.UseOAuthBearerTokens(OAuthOptions);
    
            var httpConfiguration = new HttpConfiguration();
            httpConfiguration.SuppressDefaultHostAuthentication();
            httpConfiguration.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie));
            httpConfiguration.MapHttpAttributeRoutes();
            app.UseWebApi(httpConfiguration);
    
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie))
                }
            });
        }
    }
    

    编辑 上述方法可行,但使用app.MapWhen() 功能似乎更好。

    public class Startup
    {
        public void Configure(IAppBuilder app)
        {
            // setup auth for all requests
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
    
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/account/externalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
            };
            app.UseOAuthBearerTokens(OAuthOptions);
    
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie))
                }
            });
    
            // setup webapi for only /api requests
            app.MapWhen(
                context => context.Request.Uri.PathAndQuery.StartsWith("/api"),
                newApp => {
                    var httpConfiguration = new HttpConfiguration();
                    httpConfiguration.SuppressDefaultHostAuthentication();
                    httpConfiguration.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie));
                    httpConfiguration.MapHttpAttributeRoutes();
                    app.UseWebApi(httpConfiguration);
                }
        }
    }    
    

    【讨论】:

    • 我很想知道在“MapWhen”操作中重新注册 Web API 是否是个好主意。我找不到关于如何使用“MapWhen”处理请求的可靠答案。
    猜你喜欢
    • 2019-11-02
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-07
    • 2015-05-31
    相关资源
    最近更新 更多