根据验证程序,远程证书无效-无法解决此问题 [英] The remote certificate is invalid according to the validation procedure - can`t solve this

查看:1130
本文介绍了根据验证程序,远程证书无效-无法解决此问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这个问题上挂了好几天,而且没有一个答案可以解决这个问题.

I hang unsuccessfully for days on this problem and not a single answer to different posts at different websites helped me so solve it.

我正在使用Windows 10系统并使用VisualStudio 2017实施. 我使用AspNetCore实现了以下项目:

I am working on a Windows 10 System and implementing with VisualStudio 2017. With AspNetCore I`ve implemented the following projects:

1.)Web.AuthServer:用于身份验证的IdentityServer4.

1.) Web.AuthServer: IdentityServer4 for authentication.

2.)Web.ApiServer:第一个SignalR服务器.

2.) Web.ApiServer: The first SignalR-Server.

3.)Web.ApiSwitch:第二个SignalR服务器. 它具有2个SignalR-Clients作为HostedService 两个SignalR-Server之间的桥梁".>

3.) Web.ApiSwitch: The second SignalR-Server. It has a HostedService with 2 SignalR-Clients as a "bridge" between the two SignalR-Servers.>

Web.ApiSwitch启动其HostedService,该HostedService连接到自身和Web.ApiServer,包括Web.AuthServer上的身份验证.只要它们带有一些"localhost:PORT" URL,此方法就可以很好地工作.

The Web.ApiSwitch starts his HostedService which connects to itself and the Web.ApiServer including authentication at Web.AuthServer. This worked well as long as they ran with some "localhost:PORT" URL.

现在我已经尝试使用"MyIP:PORT"运行所有项目. Web.AuthServer正在使用HTTPS和自签名证书(由OpenSSL生成). 证书本身已使用以下命令行构建:

Now I`ve tried to run all the projects with "MyIP:PORT". The Web.AuthServer is using HTTPS together with a self signed certificate (generated with OpenSSL). The certificate itself has beend build with the following command lines:

生成私钥:

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:

The file has been added to mmc:

1.)文件->添加或删除管理单元->证书->添加->计算机帐户->确定 2.)将证书(.cer)导入到个人->受信任的根证书颁发机构) 3.)将具有可导出私钥支持的pfx导入个人->证书.

1.) File -> Add or Remove Snap-ins -> Certificates -> Add -> Computer Account -> OK 2.) Import the certificate (.cer) to personal -> Trusted Root Certification Authorities) 3.) Import the pfx, with exportable private key support, to personal -> certificates.

Web.AuthServer的代码:

Code of Web.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();

Web.AuthSever-ConfigureServices:

Web.AuthSever - ConfigureServices:

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());
 });
 }

Web.AuthSever-配置:

Web.AuthSever - Configure:

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();
}

Web.AuthSever-SigninCredentialExtension:

Web.AuthSever - SigninCredentialExtension:

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的代码:

Code of 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();

Web.ApiServer-ConfigureServices:

Web.ApiServer - ConfigureServices:

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>();
}

Web.ApiServer-配置:

Web.ApiServer - Configure:

   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客户端:

Token request or SignalR clients:

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;
}

来自Web.ApiServer的ConfigureServices的TokenRetriever仅用于获取运行的SignalR客户端的身份验证,原因是它们通过查询字符串传递令牌.它完成了工作.

The TokenRetriever of ConfigureServices from Web.ApiServer is just for getting the authentication of SignalR clients running, in due to the reason that they`re passing tokens via query string. It does the job.

现在是问题:

Web.ApiServer的HostedService的客户端正尝试从Web.AuthServer获取身份验证令牌(jwt承载),但是每次我得到 以下异常:

The clients of the HostedService of Web.ApiServer are trying to get the authentication token (jwt bearer) from Web.AuthServer but every time i get the following exception:

System.Security.Authentication.AuthenticationException: 'The remote certificate is invalid according to the validation procedure.'

如果我打开浏览器并输入Web.AuthServer"MyIP:5000"的地址,那么在接受自签名证书之后,一切都可以正常工作. 但是Web.ApiServer的HostedService的客户端无法执行此操作. 如何排除此异常并获取一些有效的证书?我在客户端实施过程中缺少什么吗?希望有人可以帮助我-自4天多以来一直陷入困境.

If I open the browser and type in the adress of Web.AuthServer "MyIP:5000" everything is working fine, after I accept the self signed certificate. But the clients of the HostedService of Web.ApiServer can`t do this. How do I ged rid of this exception and get some valid certificate? Am I missing something at client implementation? Hopefully someone can help me - getting stucked at this since more than 4 days.

推荐答案

为使客户端信任服务器,客户端会检查服务器针对TLS公开的证书上的许多属性,例如预期域",证书已过期".客户端将检查的一件事是证书链,这是一个信任链.

For clients to trust a server, they check a number of properties on the certificate that the server is exposing for TLS, things such as 'is the certificate for the expected domain', 'has the certificate expired'. One of the things that the client will check is the certificate chain, which is a chain of trust.

https://knowledge.digicert.com/solution/SO16297.html

当您从证书颁发机构购买证书时,部分就是您要购买的-例如,让我们看一下Facebook使用的证书.

When you purchase a certificate from a certificate authority, this is partly what you are buying - for example, lets look at the certificate used by Facebook.

它们具有可用于facebook的所有子域的通配符证书,并且受信任的根证书颁发机构是DigiCert( https://www.digicert.com/welcome/compatibility.htm ).通过使用广受信任的Digicert CA,客户端可以知道Facebook证书是由Digicert颁发的,因此可以信任Facebook证书.

They have a wildcard certificate that will work for all sub-domains of facebook, and the trusted root certificate authority is DigiCert (https://www.digicert.com/welcome/compatibility.htm). By using the Digicert CA, which is widely trusted, the client knows that the Facebook certificate was Issued by Digicert, and it is therefore OK to trust the Facebook certifcate.

这是您缺少的部分.您使用的是自签名证书,您的客户不了解根CA,也无法建立信任链.通过手动接受证书,您可以解决根本原因,但是显然,这对于您无法完全控制的客户端不起作用.

This is the part you are missing. You're using a self-signed certificate, your clients don't know about a root CA and can't establish a chain of trust. By manually accepting the certificate, you're getting around the root cause, but obviously this doesn't work for clients you don't fully control.

https://letsencrypt.org/提供免费的CA服务,该服务现在可在大量客户端中使用-在很多方面,这是一个不错的解决方案,支持自动证书更新.因此,与其使用自签名证书,不如使用letencrypt为服务器生成证书(有关如何执行此操作的文章很多)

https://letsencrypt.org/ provide a free CA service which works in a large number of clients now - for many things it's a decent solution that supports automated certificate renewal. So, instead of using a self-signed certificate, generate a cert for your server using letsencrypt (there are loads of articles on how to do this)

使用由客户端信任的CA颁发的证书是解决此问题的正确方法.

Using a cert issued by a CA that is trusted by clients is the correct solution to this problem.

这篇关于根据验证程序,远程证书无效-无法解决此问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆