【问题标题】:Getting a 404 when accessing an [Authorize] controller when authenticated通过身份验证访问 [Authorize] 控制器时获取 404
【发布时间】:2018-02-27 13:35:26
【问题描述】:

我正在尝试在 ASP.NET MVC Core 应用程序 (.NetCore 2) 上使用 IdentityServer4 实现身份验证和访问控制。虽然这不是我第一次实现后端,但这是第一次使用 .net,我正在为一些事情苦苦挣扎。

我已按照https://identityserver4.readthedocs.io/en/release/quickstarts/1_client_credentials.html 的说明以及之前的页面进行操作。

我还添加了示例IdentityController,如下所示:

using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace leafserver.Controllers
{
    [Route("/api/identity")]
    [Authorize]
    public class IdentityController : Controller
    {
        [HttpGet]
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    }
}

我的实现与他们的示例之间存在一些差异。据我所知:

  • 我在本地网络地址 (192.168.1.x) 上提供服务,而不是本地主机
  • 他们使用的是“Web 应用程序”,而我使用的是“Web Api”
  • 他们似乎使用ControllerBase 而不是Controller 作为超类
  • 我不确定他们使用的 ASP.NET MVC 和我使用的 MVC 之间是否存在差异(我使用的是核心,他们似乎没有,但通常它应该仍然可以工作......)

我注意到以下内容:

  • 只要我不放[Authorize],一切都很好。我得到了 200 OK 的预期结果
  • [Authorize] 注释存在,但我没有使用身份验证承载令牌时,我被重定向到登录页面(由于这是一个Web api,所以它不起作用,但这是以后的问题)
  • [Authorize] 注释存在并且我使用(我认为是)正确的身份验证令牌时,我会收到 404 响应。

我原本希望得到 401 响应。 为什么我的路由不起作用,因为我使用的是身份验证令牌?

另外,我没有从服务器获取任何日志,这无济于事......

【问题讨论】:

  • 重定向是由 Web 应用检测到请求中不存在身份验证凭据引起的。 Web 应用程序正在尝试协商身份验证方案,这就是您最终使用默认 HTTP Basic 身份验证和要发布的表单的原因。获取 404 意味着 Web 应用程序已接受 Bearer 令牌进行身份验证。要更详细地排除故障,look at this answer to see how to intercept the Authorize logic
  • 就其价值而言,在 Core 中,“Web 应用程序”和“Web api”之间没有区别。这只是返回IActionResults 的控制器操作。有些可能返回 HTML,有些可能返回 JSON/XML/等。
  • 很高兴知道。有很多区别,比如services.AddMvc() vs .AddMvcCore(),或者ControllerControllerBase之间的区别(后者似乎没有在Core中使用......?)我希望更清楚.我想这可能是另一个问题。

标签: .net asp.net-core identityserver4


【解决方案1】:

对我来说,答案是像这样在我的控制器上设置 Authorize 属性

[Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]

这在最小特权指向的文档中有所概述。 https://identityserver4.readthedocs.io/en/release/topics/add_apis.html

如果我只有 [Authorize],那么它会产生 404

【讨论】:

  • 赞成。就我而言,它是[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
【解决方案2】:

好的,我找到了问题。

在我的Startup.ConfigureServices 中,我修改了添加服务的顺序。

    // https://identityserver4.readthedocs.io/en/release/quickstarts/1_client_credentials.html
    services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())
            .AddTestUsers(Config.GetTestUsers()); // TODO Remove for PROD

    // This MUST stay below the AddIdentityServer, otherwise [Authorize] will cause 404s
    services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(o =>
            {
                o.Authority = "http://localhost:5000";
                o.RequireHttpsMetadata = false; // TODO Remove for PROD
                o.ApiName = "leaf_api";
            });

如果您在身份服务器之前添加身份验证,那么您将获得 404。按照这个顺序,它工作得很好。

这是完整的Startup.cs 文件供参考:

using leafserver.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace leaf_server
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<LeafContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));

            services.AddMvcCore()
                    .AddAuthorization()
                    .AddJsonFormatters();

            // https://identityserver4.readthedocs.io/en/release/quickstarts/1_client_credentials.html
            services.AddIdentityServer()
                    .AddDeveloperSigningCredential()
                    .AddInMemoryApiResources(Config.GetApiResources())
                    .AddInMemoryClients(Config.GetClients())
                    .AddTestUsers(Config.GetTestUsers()); // TODO Remove for PROD

            // This MUST stay below the AddIdentityServer, otherwise [Authorize] will cause 404s
            services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(o =>
                    {
                        o.Authority = "http://localhost:5000";
                        o.RequireHttpsMetadata = false; // TODO Remove for PROD
                        o.ApiName = "leaf_api";
                    });

            // https://dotnetcoretutorials.com/2017/01/17/api-versioning-asp-net-core/
            services.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(1, 0);
                o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                app.UseStatusCodePages();
            }

            app.UseIdentityServer();
            app.UseAuthentication();

            app.UseMvc();
        }
    }
}

【讨论】:

  • 您通常不会将 IdentityServer 和 API 混合在同一个应用程序中 - 如果您这样做,这就是正确完成的方式:identityserver4.readthedocs.io/en/release/topics/add_apis.html
  • 很高兴知道!我想这对安全来说是有意义的。在部署到 prod 时,我会确保将这两个应用程序分开。我们现在只是在摆弄。
  • 您的声明的奇怪之处在于,在ConfigureServices 中添加服务的顺序并不重要。只有在Configure 中完成的中间件使用顺序才应该具有重要性。您确定您的诊断正确吗?
猜你喜欢
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-02
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多