Kestrel 自承载 Web API 连接超时

Kestrel self-hosted web API connection timing out

提问人:Codesmith 提问时间:11/9/2023 更新时间:11/22/2023 访问量:30

问:

我有一个使用 .Net 6 的自托管 Web API。它部署为窗口服务。我可以使用域名和端口从浏览器本地访问,但不能从另一台机器进行访问。我已经在防火墙设置中为端口定义了入站规则。这是程序.cs


var webApplicationOptions = new WebApplicationOptions() { ContentRootPath = AppContext.BaseDirectory, Args = args, ApplicationName = System.Diagnostics.Process.GetCurrentProcess().ProcessName };
var builder = WebApplication.CreateBuilder(webApplicationOptions);
builder.Host.UseWindowsService();  

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen(c =>
{
    c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory,
        $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"));

    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        In = ParameterLocation.Header,
        Description = "Please enter a valid token",
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type=ReferenceType.SecurityScheme,
                    Id="Bearer"
                }
            },
            new string[]{}
        }
    });
});


// generate lowercase URLs
builder.Services.Configure<RouteOptions>(options =>
{
    options.LowercaseUrls = true;
});

var configurationBuilder = new ConfigurationBuilder()
    .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
    .AddJsonFile("appsettings.json")
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true);
var configuration = configurationBuilder.Build();


var loggerConfig = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration);
var logger = loggerConfig.CreateLogger();
var key = Encoding.ASCII.GetBytes(configuration["Jwt:Secret"]!);

builder.Services.AddLogging(loggingBuilder =>
{
    loggingBuilder.ClearProviders();
    loggingBuilder.AddSerilog(logger);
});

builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })

// Adding Jwt Bearer
    .AddJwtBearer(options =>
    {
        options.SaveToken = true;
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidAudience = configuration["JWT:ValidAudience"],
            ValidIssuer = configuration["JWT:ValidIssuer"],
            IssuerSigningKey = new SymmetricSecurityKey(key)
        };
        options.Events = new JwtBearerEvents
        {
            OnChallenge = async context =>
            {
                // Call this to skip the default logic and avoid using the default response
                context.HandleResponse();
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.Response.ContentType = "application/json";

                var result = JsonConvert.SerializeObject(new
                {
                    code = ResponseCode.UnauthorizedDueToInvalidToken.ToCode(),
                    message = ResponseCode.UnauthorizedDueToInvalidToken.ToMessage(),
                });

                context.Response.WriteAsync(result);
            }
        };
    });

var tokenValidationParameters = new TokenValidationParameters
{
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(key),
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidateLifetime = false,
    RequireExpirationTime = false,

    // Allow to use seconds for expiration of token
    // Required only when token lifetime less than 5 minutes
    // THIS ONE
    ClockSkew = TimeSpan.Zero
};

builder.Services.AddSingleton(tokenValidationParameters);

var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}


app.UseAuthentication();
app.UseAuthorization(); 
app.MapControllers();
 
app.Run();

这是我在appsetting.json中的红隼部分

"Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:7504"
      },
      "Https": {
        "Url": "https://*:7503",
        "Certificate": {
          "Path": "D:/Certificates/Cert.pfx",
          "Password": "********"
        }
      }
    }
asp.net-core asp.net-web-api windows-services kestrel-http-server kestrel

评论

0赞 D A 11/9/2023
检查防病毒....我在端口上遇到了类似的问题......
0赞 Guru Stron 11/9/2023
您能否举例说明本地可访问的地址?
0赞 Codesmith 11/10/2023
@GuruStron example.com:7503.api/v1/myController 当我尝试localhost:7503/api/v1/myController时,它说“此服务器无法证明它是localhost;其安全证书来自 example.com”
0赞 Codesmith 11/10/2023
我什至尝试了“Url”:“example.com:7503”,
0赞 Ruikai Feng 11/10/2023
你试过生成器吗?WebHost.UseUrls(“http://*:p ort”); ?

答:

0赞 Codesmith 11/22/2023 #1

这不是任何配置或代码问题。这是主机网络上的网络安全问题。