在Nginx反向代理后使用Duende Identity Server

w8rqjzmb  于 2023-01-25  发布在  Nginx
关注(0)|答案(1)|浏览(184)

概述

我有一个微服务解决方案,其中包括Blazor应用程序、Web API服务和Duende Identity Server。此外,我使用Nginx作为反向代理来访问服务。当我将Blazor应用程序配置为直接使用Duende进行身份验证时,它可以正常工作,但当我想在它们之间添加Nginx时,它无法工作。我遵循了IdentityServer/IdentityServer4#1623(comment)来解决这个问题,但我没能成功。下面,我描述服务配置和我目前正在做的事情:

Nginx

Nginx.conf的配置如下所示:

worker_processes  1;
events {
     worker_connections  1024;
}
http {
     include       mime.types;
     default_type  application/octet-stream;
     log_format  main  '[$time_local]-status :[$status] - $remote_addr - $host - UriAddr: [$request_uri] - XFF : ["$http_x_forwarded_for"] '
                  '- BodyByteSent : [$body_bytes_sent] "$http_referer" '
                  '"$request"'; #"$http_user_agent"
     access_log  logs/access.log  main;
     sendfile        on; 
     keepalive_timeout  300;   
     include nginx_http.conf;  
}

并且nginx_http.conf已经配置如下:

server {
    listen       80;
    server_name  localhost;
    server_tokens off;

    gzip on;
    gzip_buffers      16 8k;
    gzip_comp_level   4;
    gzip_http_version 1.0;
    gzip_min_length   1280;
    gzip_types        *;
    gzip_vary         on;    
    gzip_disable msie6;
    charset UTF-8;
    include nginx_access_control.conf;
    location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host $http_host;
        #proxy_set_header Referer $http_referer;

        proxy_pass         https://127.0.0.1:5001/;
    }
location /Identity/ {
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass         http://127.0.0.1:12000/;
    }

}

Duende身份服务

此服务在https://localhost:12001/和HTTP://localhost:12000/上运行,带有dotnet 6。Identity Server配置如下:

builder.Services.AddIdentityServer(options =>
{
    options.IssuerUri = "http://localhost/Identity/";
})
 .AddDeveloperSigningCredential()
.AddInMemoryClients(new List<Client>
{
    new Client
    {
        ClientName = "Web User",
        ClientId = "web",/*"D2B8B5EC-9766-40B9-9D95-077B54245E6E",*/
        ClientSecrets= {new Secret("123456".Sha256())},
        AllowedGrantTypes = GrantTypes.Code,
        // RedirectUris={"https://localhost:5001/signin-oidc"},
        RedirectUris={"http://localhost/signin-oidc"},
        PostLogoutRedirectUris={ "http://localhost/signout-callback-oidc" },
        AllowedScopes=
        {
            "openid",
            "profile"
        }
    }
}).AddInMemoryIdentityResources(new List<IdentityResource>
{
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
})
.AddInMemoryApiScopes(new List<ApiScope>
{
    new ApiScope("Management.fullaccess")
})
.AddInMemoryApiResources(new List<ApiResource>
{
    new ApiResource("Management","Management Service")
    {
        Scopes = { "Management.fullaccess" }      
    }
})
.AddAspNetIdentity<User>();

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();

app.MapRazorPages();
app.MapControllers();
app.Run();

Blazor应用程序

此服务在https://localhost:5001/和HTTP://localhost:5000/上运行,使用dotnet 5。启动配置如下所示:

public void ConfigureServices(IServiceCollection services)
    {
        var blazorSevice = services.AddControllersWithViews();

        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders =
                ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        });
        if (environment.IsDevelopment())
        {
            blazorSevice.AddRazorRuntimeCompilation();
        }
        services.AddRazorPages();
        services.AddServerSideBlazor(o => o.DetailedErrors = true);
        services.AddAuthentication(p =>
            {
                p.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                p.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {
                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.Authority = "http://localhost/Identity";//"http://localhost:12000";
                options.MetadataAddress = "http://localhost/Identity/.well-known/openid-configuration";
                options.ClientId = "web";
                options.ClientSecret = "123456";
                options.ResponseType = "code";
                options.GetClaimsFromUserInfoEndpoint = true;
                options.Scope.Add("profile");
                options.Scope.Add("openid");
                options.SaveTokens = true;
                options.RequireHttpsMetadata = false;
                
            });

        services.AddTelerikBlazor();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseForwardedHeaders();

        app.Use(async (httpcontext, next) =>
        {
            await next();
            string location = httpcontext.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Location];

            if ((httpcontext.Response.StatusCode == StatusCodes.Status302Found
                || httpcontext.Response.StatusCode == StatusCodes.Status307TemporaryRedirect)
                && location != "https://localhost:5001/signin-oidc"
                && location != "https://localhost:5001/")
            {
                location = location.Replace("https","http")
                    .Replace("://localhost:5001/", "://localhost/Identity/");
                httpcontext.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Location] = location;
            }
            if (httpcontext.Response.StatusCode == StatusCodes.Status302Found
                || httpcontext.Response.StatusCode == StatusCodes.Status307TemporaryRedirect)
            {
                if (location != "https://localhost:5001/" 
                    && location != "https://localhost:5001/signin-oidc" 
                    && !location.Contains("://localhost/Identity/"))
                {
                    location = location.Replace("%3A5001", "")
                        .Replace("://localhost/", "://localhost/Identity/")
                        .Replace("://localhost:12001/", "://localhost/Identity/");
                    httpcontext.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Location] = location;
                }
            }
        });
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
            endpoints.MapControllers();
        
            endpoints.MapBlazorHub(option =>
                option.Transports = HttpTransportType.LongPolling);
            endpoints.MapFallbackToPage("/_Host");
        });
    }

在上面的代码中,我尝试使用中间件更改HTTP响应位置以重定向属于Duende Identity Server的请求,但我认为这不是一种常用的方法!使用上面显示的所有配置,现在,当我运行blazor应用程序时,它重定向到Duende服务中的登录页面,但当我单击登录按钮时,它重定向到/signin-oidc route并显示错误:

似乎重定向到/signin-oidc后,blazor应用试图从Duende服务中的/connect/token获取令牌,并返回错误。我搜索了类似的解决方案,但没有找到任何东西!有人能帮助我吗?

wkyowqbh

wkyowqbh1#

最有可能的问题在于缺少了x-forwarded-for头,你需要使用这些头来告诉duende你有一个反向代理。
您可以通过在管道的开头添加以下中间件来添加标头:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

相关问题