Удаленный сертификат недействителен в соответствии с процедурой проверки
Здравствуйте вместе,
Я безуспешно висел целыми днями над этой проблемой, и ни один ответ на разные посты на разных сайтах не помог мне так решить ее.
Я работаю над системой Windows 10 и внедряю ее с помощью VisualStudio 2017.
С помощью AspNetCore я реализовал следующие проекты:
1.) паутина.AuthServer: IdentityServer4 для аутентификации.
2.) Web.ApiServer: Первый SignalR-сервер.
3.) Web.ApiSwitch: Второй SignalR-сервер.
Он имеет HostedService с 2 SignalR-клиентами в качестве
"мост" между двумя SignalR-серверами.>
Web.ApiSwitch запускает свой HostedService, который подключается к себе и Web.ApiServer, включая аутентификацию в Интернете.AuthServer. Это хорошо работало до тех пор, пока они работали с некоторым URL-адресом "localhost:PORT".
Теперь я попробовал запустить все проекты с помощью "MyIP:PORT". сеть.AuthServer использует HTTPS вместе с самозаверяющим сертификатом (генерируемым с помощью OpenSSL).
Сам сертификат был создан с помощью следующих командных строк:
Генерация закрытого ключа:
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout IdentityServer4Auth.key -out IdentityServer4Auth.crt -subj "/CN=example.com" -days 3650
Генерация сертификата:
openssl pkcs12 -export -out IdentityServer4Auth.pfx -inkey IdentityServer4Auth.key -in IdentityServer4Auth.crt -certfile IdentityServer4Auth.crt
Файл был добавлен в mmc:
1.) Файл -> Добавить или удалить Оснастки -> сертификаты -> Добавить -> учетная запись компьютера -> ОК
2.) импортируйте сертификат (.cer) в личные Доверенные корневые центры сертификации)
3.) Импортировать файл с экспортируемым закрытым ключом поддержки, личный -&ГТ; сертификаты.
Код веба.AuthServer:
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseKestrel(options => { options.Listen(IPAddress.Any, 5000, listenOptions => { listenOptions.UseHttps(); }); }) .UseStartup<Startup>() .ConfigureLogging(builder => { builder.ClearProviders(); builder.AddSerilog(); }) .Build();
public void ConfigureServices(IServiceCollection services) { // Gets connection strings from "appsettings.json". string csApplicationContext = Configuration.GetConnectionString("ApplicationContext"); string csConfigurationStore = Configuration.GetConnectionString("ConfigurationStore"); var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; var settings = JsonFileManager<ServerSettings>.Load(AppDomain.CurrentDomain.BaseDirectory + "Config\\svConf.json"); // Add cross origin resource sharing. services.AddCors(options => { options.AddPolicy("default", policy => { policy.WithOrigins(settings.CorsOrigins) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // Add bearer token authentication. services.AddAuthentication() .AddJwtBearer(jwt => { jwt.Authority = settings.JWTBearerSettings.Authority; jwt.Audience = settings.JWTBearerSettings.Audience; jwt.RequireHttpsMetadata = settings.JWTBearerSettings.RequireHttpsMetadata; jwt.Validate(); }); services.AddPolicyServerClient(Configuration.GetSection("Policy")) .AddAuthorizationPermissionPolicies(); // DB und User registieren für DI services.AddDbContext<ApplicationDbContext>(builder => builder.UseSqlite(csApplicationContext, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly))); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddTransient<IClientStore, ClientService>(); // Add IS4 as authentication server. var is4Builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; options.Events.RaiseInformationEvents = true; }) // Add config data (clients, resources, CORS). .AddConfigurationStore(options => options.ConfigureDbContext = builder => builder.UseSqlite(csConfigurationStore, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly))) .AddClientStore<ClientService>() .AddAspNetIdentity<ApplicationUser>(); SigninCredentialExtension.AddSigninCredentialFromConfig(is4Builder, Configuration.GetSection("SigninKeyCredentials"), Logger); services.AddMvc(options => { // this sets up a default authorization policy for the application // in this case, authenticated users are required (besides controllers/actions that have [AllowAnonymous] var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); options.SslPort = 5000; options.Filters.Add(new RequireHttpsAttribute()); }); }
public async void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); else app.UseExceptionHandler("/Home/Error"); // Use specific cross origin resource sharing configuration. app.UseCors("default"); app.UseDefaultFiles(); app.UsePolicyServerClaims(); app.UseStaticFiles(); app.UseHttpsRedirection(); app.UseIdentityServer(); // Adding test data to database. await InitializeDbTestData.GenerateTestData(app); app.UseMvcWithDefaultRoute(); }
public static class SigninCredentialExtension { private const string KeyType = "KeyType"; private const string KeyTypeKeyFile = "KeyFile"; private const string KeyTypeKeyStore = "KeyStore"; private const string KeyTypeTemporary = "Temporary"; private const string KeyFilePath = "KeyFilePath"; private const string KeyFilePassword = "KeyFilePassword"; private const string KeyStoreIssuer = "KeyStoreIssuer"; public static IIdentityServerBuilder AddSigninCredentialFromConfig( this IIdentityServerBuilder builder, IConfigurationSection options, ILogger logger) { string keyType = options.GetValue<string>(KeyType); logger.LogDebug($"SigninCredentialExtension keyType is {keyType}"); switch (keyType) { case KeyTypeTemporary: logger.LogDebug($"SigninCredentialExtension adding Developer Signing Credential"); builder.AddDeveloperSigningCredential(); break; case KeyTypeKeyFile: AddCertificateFromFile(builder, options, logger); break; case KeyTypeKeyStore: AddCertificateFromStore(builder, options, logger); break; } return builder; } public static X509Certificate2 GetCertificateByThumbprint(string thumbprint) { using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { certStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); if (certCollection.Count > 0) return certCollection[0]; } return null; } private static void AddCertificateFromStore(IIdentityServerBuilder builder, IConfigurationSection options, ILogger logger) { var keyIssuer = options.GetValue<string>(KeyStoreIssuer); logger.LogDebug($"SigninCredentialExtension adding key from store by {keyIssuer}"); X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); var certificates = store.Certificates.Find(X509FindType.FindByIssuerName, keyIssuer, true); if (certificates.Count > 0) { builder.AddSigningCredential(certificates[0]); builder.AddValidationKey(certificates[0]); } else logger.LogError("A matching key couldn't be found in the store"); } private static void AddCertificateFromFile(IIdentityServerBuilder builder, IConfigurationSection options, ILogger logger) { var keyFilePath = options.GetValue<string>(KeyFilePath); var keyFilePassword = options.GetValue<string>(KeyFilePassword); if (File.Exists(keyFilePath)) { logger.LogDebug($"SigninCredentialExtension adding key from file {keyFilePath}"); builder.AddSigningCredential(new X509Certificate2(keyFilePath, keyFilePassword)); } else { logger.LogError($"SigninCredentialExtension cannot find key file {keyFilePath}"); } } }
Код Web.ApiServer:
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseKestrel(options => { options.Listen(IPAddress.Any, 5004, listenOptions => { listenOptions.UseHttps(); }); }) .UseStartup<Startup>() .ConfigureLogging(builder => { builder.ClearProviders(); builder.AddSerilog(); }) .Build();
public void ConfigureServices(IServiceCollection services) { // Add cross origin resource sharing. services.AddCors(options => { options.AddPolicy("default", policy => { policy.WithOrigins(_settings.CorsOrigins) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // Add bearer token authentication and our IS4 as authentication server. services.AddAuthentication(_settings.ISAuthenticationSettings.DefaultScheme) .AddIdentityServerAuthentication(options => { options.Authority = _settings.ISAuthenticationSettings.Authority; options.RequireHttpsMetadata = _settings.ISAuthenticationSettings.RequireHttpsMetadata; options.ApiName = _settings.ISAuthenticationSettings.ApiName; // Handling the token from query string in due to the reason // that signalR clients are handling them over it. options.TokenRetriever = new Func<HttpRequest, string>(req => { var fromHeader = TokenRetrieval.FromAuthorizationHeader(); var fromQuery = TokenRetrieval.FromQueryString(); return fromHeader(req) ?? fromQuery(req); }); options.Validate(); }); // Add singalR as event bus. services.AddSignalR(options => options.EnableDetailedErrors = true); services.AddMvcCore(options => { options.SslPort = 5003; options.Filters.Add(new RequireHttpsAttribute()); }) .AddAuthorization() .AddJsonFormatters(); // Register ConnectionHost as hosted service with its wrapper class. services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, ConnectionHost>(); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); app.UseHttpsRedirection(); // Has to be called before UseSignalR and UseMvc! app.UseAuthentication(); // Use specific cross origin resource sharing configuration. app.UseCors("default"); app.UseSignalR(routes => routes.MapHub<EventHub>("/live")); app.UseMvc(); }
Запрос токена для клиентов SignalR:
public static async Task<TokenResponse> RequestTokenAsync(string authority, string clientID, string scope) { var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync(authority); if (disco.IsError) throw new Exception(disco.Error); var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = clientID, ClientSecret = "SomeTestSecret", Scope = scope }); if (response.IsError) { throw new Exception(response.Error); } return response; }
TokenRetriever ConfigureServices от Web.ApiServer предназначен только для проверки подлинности запущенных клиентов SignalR по той причине, что они передают токены через строку запроса. Он делает свою работу.
Теперь проблема:
Клиенты HostedService Web.ApiServer пытаются получить токен аутентификации (jwt bearer) из Web.AuthServer но каждый раз когда я получаю
следующее исключение:
System.Security.Authentication.AuthenticationException: 'The remote certificate is invalid according to the validation procedure.'
Если я открываю браузер и введите адрес веб-страницы.AuthServer "MyIP:5000" все работает нормально, после того как я принимаю самозаверяющий сертификат.
Но клиенты HostedService Web.ApiServer не могут этого сделать.
Как мне избавиться от этого исключения и получить какой-то действительный сертификат? Может быть, я что-то упустил при реализации клиента? Надеюсь, кто - то сможет мне помочь-я застрял на этом уже более 4 дней.
Что я уже пробовал:
- Создание различных сертификатов с помощью EasyRSA, OpenSSL, инструментов из Windows Kits 10.
- Изменения кода сервера.. чтобы многое здесь записать.