LWP::UserAgent change SSL implementation

2019-09-19 23:31发布

I want to use LWP::UserAgent to send some requests over HTTPS. There is this sentence in the ssl_opts section in the documentation

Other options can be set and are processed directly by the SSL Socket implementation in use. See IO::Socket::SSL or Net::SSL for details.

I have installed both modules on my machine and I think I have some problems because of it.

How can I find out which one is in use and how to change it to use the other module?

标签: perl ssl
1条回答
做自己的国王
2楼-- · 2019-09-20 00:13

How can I find out which one is in use

If you look at LWP::UserAgent documentation it says you need to install LWP::Protocol::https module to have support for https:// URIs.

If you look at this module in turn you see that it does use the Net::HTTP distribution, into which you find a HTTPS.pm module (see it online at https://metacpan.org/source/OALDERS/Net-HTTP-6.18/lib/Net/HTTPS.pm) where at the beginning you can clearly see that, except if overriden, it first start to try using IO::Socket::SSL and next only searches for Net::SSL.

See:

elsif ($IO::Socket::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded
}
elsif ($Net::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "Net::SSL";
}

If they are not loaded yet, it tries to load them, in the same order:

eval { require IO::Socket::SSL; };
if ($@) {
    my $old_errsv = $@;
    eval {
        require Net::SSL;  # from Crypt-SSLeay
    };
    if ($@) {
        $old_errsv =~ s/\s\(\@INC contains:.*\)/)/g;
        die $old_errsv . $@;
    }
    $SSL_SOCKET_CLASS = "Net::SSL";
}
else {
    $SSL_SOCKET_CLASS = "IO::Socket::SSL";
}

So, in short, IO::Socket::SSL has full precedence.

Inside your program, after having used LWP::UserAgent you can use the $Net::HTTPS::SSL_SOCKET_CLASS variable to know which class has been used for HTTPS operations.

how to change it to use the other module?

If you read the beginning of the code you will see:

elsif ($SSL_SOCKET_CLASS = $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}) {
    unless ($SSL_SOCKET_CLASS =~ /^(IO::Socket::SSL|Net::SSL)\z/) {
        die "Bad socket class [$SSL_SOCKET_CLASS]";
    }
    eval "require $SSL_SOCKET_CLASS";
    die $@ if $@;
}

which means that before everything above if the environment has a variable PERL_NET_HTTPS_SSL_SOCKET_CLASS defined, then its value is used as a class to do operations, if its name is either IO::Socket::SSL or Net::SSL.

So, either set it in your environment before starting your program that uses LWP::UserAgent or do something like that in your program:

BEGIN {
    $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = 'Net::SSL';
}

This needs to happen before you do use LWP::UserAgent;

查看更多
登录 后发表回答