You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker环境下.NET 6 API集成Keycloak认证始终失败求助

.NET 6 API容器化后Keycloak认证401问题解决

核心问题分析

非容器环境正常、容器化后401的核心原因:

  1. 容器网络访问不匹配:API容器内使用host.docker.internal访问Keycloak,但Keycloak同属一个Docker网络,应使用服务名keycloak进行内部访问
  2. JWT Issuer验证不通过:Keycloak生成的Token Issuer是外部访问地址(http://localhost:8080/realms/test),而API容器内配置的Authority是内部地址,两者不匹配触发验证失败
  3. Keycloak前端URL配置错误:KEYCLOAK_FRONTEND_URL设为test.orderapi,导致前端登录跳转地址异常
  4. 端口配置无效:docker-compose.override.yml中API的端口配置- "8"格式错误,无法正常映射外部访问端口

分步修正方案

1. 修正Program.cs的认证配置

调整Authority为Docker网络内的Keycloak服务名,添加多Issuer支持并增加调试日志:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Test.OrderApi.Settings;

var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();       
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>
            {
                // 改用Docker网络内的Keycloak服务名访问
                o.Authority = "http://keycloak:8080/realms/test";
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false,
                    // 同时支持外部和内部Issuer,匹配Token中的Issuer值
                    ValidIssuers = new[] 
                    { 
                        "http://localhost:8080/realms/test", 
                        "http://keycloak:8080/realms/test" 
                    }
                };

                o.RequireHttpsMetadata = false;
                // 添加认证失败日志,方便调试问题
                o.Events = new JwtBearerEvents
                {
                    OnAuthenticationFailed = context =>
                    {
                        Console.WriteLine($"认证失败详情: {context.Exception.Message}");
                        if (context.Exception is SecurityTokenInvalidIssuerException issuerEx)
                        {
                            Console.WriteLine($"无效Issuer: {issuerEx.InvalidIssuer}, 允许的Issuer列表: {string.Join(", ", issuerEx.ValidIssuers)}");
                        }
                        return Task.CompletedTask;
                    }
                };
            });

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// 开发环境注释HTTPS重定向,避免容器内HTTP访问被强制跳转
// app.UseHttpsRedirection();

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

app.MapControllers();

app.Run();

2. 修正docker-compose.yml的Keycloak配置

调整KEYCLOAK_FRONTEND_URL为外部可访问地址,修复PostgreSQL配置错误:

version: '3.4'

services:
  test.orderapi:
    container_name: order-api
    image: ${DOCKER_REGISTRY-}testorderapi
    build:
      context: .
      dockerfile: tests/TestDummyMicroservices/Test.Order.Api/Dockerfile
    networks:
      - keycloak_network
   
  postgres_keycloak:
    container_name: postgres-keycloak
    image: postgres:14.6
    command: postgres -c 'max_connections=200'
    volumes:
      - pgdata_keycloak:/var/lib/postgresql/data  # 修正拼写错误:postgressql -> postgresql
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]  # 替换为真实的PostgreSQL健康检查
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "5436:5432"
    networks:
      - keycloak_network

  keycloak:
    container_name: keycloak
    image: quay.io/keycloak/keycloak:20.0.3
    command: start-dev
    environment: 
        KC_DB: postgres
        KC_DB_URL_HOST: postgres_keycloak
        KC_DB_URL_DATABASE: keycloak
        KC_DB_PASSWORD: password
        KC_DB_USERNAME: keycloak
        KC_DB_SCHEMA: public
        KEYCLOAK_ADMIN: admin
        KEYCLOAK_ADMIN_PASSWORD: admin
        # 修正前端访问URL为外部可访问地址
        KEYCLOAK_FRONTEND_URL: http://localhost:8080
        KC_HTTP_ENABLED: true
        KC_HTTP_PORT: 8080
    depends_on:
        postgres_keycloak:
          condition: service_healthy
    ports:
        - "8080:8080"
    networks:
      - keycloak_network

volumes:
  pgdata_keycloak:
networks:
  keycloak_network:
    driver: bridge

3. 修正docker-compose.override.yml的API端口配置

调整为有效的端口映射格式,方便外部访问API:

version: '3.4'
services:
  test.orderapi:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
    ports:
      # 外部端口5000映射到容器80端口,外部可通过http://localhost:5000访问API
      - "5000:80"

  # 若test.gateway未在主docker-compose.yml中定义,可暂时移除该配置
  # test.gateway:
  #   environment:
  #     - ASPNETCORE_ENVIRONMENT=Development
  #   ports:
  #     - "80:80"

验证步骤

  1. 重新启动容器:docker-compose down && docker-compose up --build
  2. 测试API容器与Keycloak的网络连通性:
    docker exec -it order-api curl http://keycloak:8080/realms/test/.well-known/openid-configuration
    
    返回JSON格式的OpenID配置则说明网络连通正常
  3. 查看API容器日志,确认无认证相关错误:
    docker logs order-api
    
  4. 使用Postman或Swagger访问http://localhost:5000,携带Keycloak生成的Token请求API,验证是否返回200正常响应

内容的提问来源于stack exchange,提问作者Getraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:06:56