首页 文章

Identityserver4 API身份验证无法按预期工作

提问于
浏览
0

我已经坚持了这个问题将近一个月,所以任何帮助都表示赞赏 . 让我们来解决问题:我在一个项目中有一个身份服务器和用户管理API(基于CRUD) . 身份服务器本身作为其他网站的登录/注册页面(我目前只有一个ASP.NET框架MVC网站) . 该API用于从MVC项目和移动应用程序检索和更新用户配置文件 . 身份服务器和MVC项目由docker容器备份 .

API身份验证通过身份服务器承载令牌完成 . 因此,API身份验证在localhost上完美运行,但是,当我将身份服务器部署到Azure容器实例时,API将停止工作,无论是MVC还是Postman . 我得到的错误是:

处理请求时发生未处理的异常 . WinHttpException:操作超时System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()HttpRequestException:发送请求时发生错误 . System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()IOException:IDX10804:无法从以下位置检索文档:'http://taxrefund-identity.westeurope.azurecontainer.io/.well-known/openid-configuration' . Microsoft.IdentityModel.Protocols.HttpDocumentRetriever d__8.MoveNext()InvalidOperationException:IDX10803:无法从以下位置获取配置:'http://taxrefund-identity.westeurope.azurecontainer.io/.well-known/openid-configuration' . Microsoft.IdentityModel.Protocols.ConfigurationManager d__24.MoveNext()

最奇怪的是,我可以通过浏览器访问发现 endpoints ,没有任何问题 .

我的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFrameworkSqlServer()
                .AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                        sqlServerOptionsAction: sqlOptions =>{
                            sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                        }), ServiceLifetime.Scoped
                 );
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
        services.AddTransient<IEmailSender, EmailSender>();
        services.AddScoped<DatabaseInitializer>();
        services.AddCors();
        // Adds IdentityServer
        var cert = new X509Certificate2(Path.Combine(Environment.ContentRootPath, "idsrv3test.pfx"), "idsrv3test");
        services.AddIdentityServer()
            .AddSigningCredential(cert)
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())
            .AddAspNetIdentity<ApplicationUser>()
            .Services.AddTransient<IProfileService, ProfileService>();

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        services.AddAuthentication()
            .AddGoogle("Google", options =>
            {
                options.ClientId = "**";
                options.ClientSecret = "**";
            })
            .AddMicrosoftAccount("Microsoft", options =>
            {
                options.ClientId = "**";
                options.ClientSecret = "**";
            });
        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(o =>
            {
                o.Authority = "http://taxrefund-identity.westeurope.azurecontainer.io/";
                o.ApiName = "Profile.API";
                o.ApiSecret = "**";
                o.RequireHttpsMetadata = false;
            });
        services.AddMvc();
        services.AddAntiforgery();
    }

配置方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, RoleManager<IdentityRole> roleManager, ApplicationDbContext context, UserManager<ApplicationUser> userManager)
    {
        loggerFactory.AddDebug();
        loggerFactory.AddConsole(LogLevel.Trace);
        loggerFactory.AddFile("logs.txt");

        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
        app.UseBrowserLink();
        app.UseCors(policy =>
        {
            policy.AllowCredentials();
            policy.AllowAnyOrigin();
            policy.AllowAnyHeader();
            policy.AllowAnyMethod();
            policy.WithExposedHeaders("WWW-Authenticate");
        });

        app.UseStaticFiles();
        app.UseIdentityServer();
        app.UseAuthentication();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
        context.Database.Migrate();
        DatabaseInitializer.SeedData(roleManager);
    }

API资源配置:

new ApiResource("Profile.API", "Profile management API")
{
    UserClaims = { ClaimTypes.Role },
    ApiSecrets =
    {
        new Secret("**".Sha256())
    }
}

我像这样保护我的API:

[Authorize(AuthenticationSchemes = "Bearer")]
[Route("api/Users")]
[Produces("application/json")]
public class ApplicationUsersAPIController : ControllerBase

要访问它,我从/ connect / token endpoints 请求一个令牌(使用客户端凭据或资源所有者密码/用户名),然后在Authorization标头中使用它以及后续请求 .

我一直坚持这个问题已经持续了一个月 - 现在它变得令人沮丧 . 我已经阅读了与此问题相关的所有帖子,但没有一个解决方案有帮助 . 我曾尝试降级到早期版本的system.net.http,不同的证书和更多帮助其他人的解决方案 .

此外,没有[Authorize]属性的 endpoints 也可以正常工作 .

我唯一没有尝试的是安装SSL证书并使我的网址https - 我读到这不应该影响身份服务器的功能 . 我现在没有实际需要,所以如果有必要请告诉我 .

如果我需要更多信息,请告诉我 .

非常感激 .

1 回答

  • 0

    最终的解决方案是更改 AddIdentityServerAuthentication 中的权限URL:

    services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(o =>
                {
                    o.Authority = "http://taxrefund-identity.westeurope.azurecontainer.io/";
                    o.ApiName = "Profile.API";
                    o.ApiSecret = "**";
                    o.RequireHttpsMetadata = false;
                });
    

    至:

    services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(o =>
                    {
                        o.Authority = "http://localhost/"; //crucial part
                        o.ApiName = "Profile.API";
                        o.ApiSecret = "**";
                        o.RequireHttpsMetadata = false;
                    });
    

    这实际上是有道理的,因为在这种情况下,身份服务器和API在同一容器实例/进程中运行,因此,它无法通过DNS URL自行访问它,相反,它可以通过 localhost 访问自己URL .

相关问题