【问题标题】:Mojo::UserAgent certificate verify failedMojo::UserAgent 证书验证失败
【发布时间】:2016-05-13 19:52:39
【问题描述】:

我想访问一个无法验证证书的网站(主机名不正确,我无法更改/更新我的应用程序指向的服务器上的证书)。我正在使用Mojo::UserAgent 来获取请求。那么如何忽略这一点并继续连接到网站呢? 我已经看到没有选项。

我不想使用LWP::UserAgent

我已经使用 WWW::CurlWWW::Curl::Easy 完成了它,但我想使用 Mojo::UserAgent 清理代码(在我的整个应用程序中使用)。

【问题讨论】:

    标签: perl ssl curl mojolicious


    【解决方案1】:

    主机名不正确......那么如何忽略这一点并继续连接到网站?

    仅仅因为主机名与证书不匹配就放弃任何类型的验证是一个非常糟糕的主意。为什么要使用 TLS?

    更好的方法是预先知道您期望获得哪个证书,并验证您是否确实获得了该证书。这可以通过选项SSL_fingerprint 轻松完成。不幸的是 Mojo::UserAgent 没有提供设置连接特定参数的方法,因此您需要在连接之前立即设置它,然后在进行其他连接之前设置它:

    use IO::Socket::SSL 1.980;
    IO::Socket::SSL::set_client_defaults(
        SSL_fingerprint => "sha256$55a5dfaaf..."
    );
    ... use Mojo::UserAgent to connect ..
    IO::Socket::SSL::set_client_defaults(); # set back
    

    有关使用此选项以及如何获取指纹的更多信息,请参阅Certificate error in Perl

    如果只有主机名不正确,另一种方法是使用 SSL_verifycn_name 选项指定您希望在证书中使用的主机名。

    IO::Socket::SSL::set_client_defaults(
        SSL_verifycn_name => 'foo.example.com',
    );
    

    另一种方法可以使用set_args_filter_hack 函数完成,该函数旨在处理设置奇怪默认值或不允许用户设置自己的值的模块:

    my $hostname = undef;
    IO::Socket::SSL::set_args_filter_hack(
        sub {
            my ($is_server,$args) = @_;
            $args->{SSL_verifycn_name} = $hostname if $hostname;
        }
    );
    ...
    $hostname = 'foo.example.com';
    ... do something with Mojo::UserAgent ...
    $hostname = undef;
    

    这样您可以调整每次 SSL 握手的设置。

    更多信息请参见documentation of IO::Socket::SSL,尤其是关于常见使用错误的部分。这部分还记录了如果证书的某些部分错误,您应该做什么,而不是禁用任何类型的验证。


    'SSL connect attempt failed error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol'
    curl ... SSL connection using TLS_RSA_WITH_RC4_128_MD5
    

    我的猜测是您在这里面临的与证书验证无关。鉴于该服务器使用的是非常古老的密码 RC4-MD5,我将假设该服务器只能处理 SSL 3.0。出于安全原因,该版本在 IO::Socket::SSL 中被禁用了一段时间。暂时显式使用这个不安全的版本:

    IO::Socket::SSL::set_client_defaults(
        SSL_version => 'SSLv3'
    );
    

    【讨论】:

      【解决方案2】:

      Mojo::UserAgent 使用 IO::Socket::SSL 支持 SSL/TLS,因此您可以使用禁用服务器证书验证

      IO::Socket::SSL::set_defaults(
          SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
      );
      

      【讨论】:

      • 我已经添加了你写的代码,但我的日志显示它没有用:(错误结果:'error' => { 'message' => 'SSL connect attempt failed error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol' },
      • @Elia Bellussi,实际上,我认为这个答案确实执行了请求的任务,并且您现在正在经历第二个problem
      • 使用curl -k 没关系。这里是选项代码:$curl->setopt(CURLOPT_SSL_VERIFYPEER,0); 和输出:* warning: ignoring value of ssl.verifyhost * skipping SSL peer certificate verification * SSL connection using TLS_RSA_WITH_RC4_128_MD5 。所以我认为这只是证书的问题。
      • 这会禁用该程序中每个 IO::Socket::SSL (LWP, Mojo, Net::SMTP, ....) 用户的任何类型的验证。如果您在模块中执行此操作,这将影响使用该模块的每个程序。我认为这是个坏主意。
      • 是的,唯一阻止你的是你可能没有意识到这会影响使用 IO::Socket::SSL 作为副作用的其他任何东西,并且你不知道你需要到以及如何重置它。也许您可以将这些信息添加到您的答案中。
      【解决方案3】:

      这是一个老问题,但 Mojolicious 是活生生的。因此,我最近一直在与此作斗争。直接来自文档:

      my $bool = $ua->insecure;
      $ua      = $ua->insecure($bool);
      

      访问 HTTPS/WSS 站点不需要有效的 TLS 证书,默认为 MOJO_INSECURE 环境变量的值。

      # Disable TLS certificate verification for testing
      say $ua->insecure(1)->get('https://127.0.0.1:3000')->result->code;
      

      在我的应用程序中,$bool 是从配置文件中设置的,所以我可以在需要的地方重新打开它。

      【讨论】:

        猜你喜欢
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-15
        • 2022-01-15
        • 2018-03-15
        • 2015-11-13
        • 2021-11-26
        • 2018-09-10
        相关资源
        最近更新 更多