概述
我有一个微服务解决方案,其中包括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获取令牌,并返回错误。我搜索了类似的解决方案,但没有找到任何东西!有人能帮助我吗?
1条答案
按热度按时间wkyowqbh1#
最有可能的问题在于缺少了x-forwarded-for头,你需要使用这些头来告诉duende你有一个反向代理。
您可以通过在管道的开头添加以下中间件来添加标头: