我想访问一个需要用户名/密码的URL。我想用curl访问它。现在我正在做的事情是:

curl http://api.somesite.com/test/blah?something=123

我得到一个错误。我想我需要在上面的命令中指定用户名和密码。

我该怎么做呢?


当前回答

要让密码至少不弹出在你的.bash_history:

curl -u user:$(cat .password-file) http://example-domain.tld

其他回答

这比OP要求的要多得多,但由于这是安全传递密码给curl的顶级结果,我在这里添加了这些解决方案,以供其他人到达这里搜索。


注意:-s arg for read命令不是POSIX,所以不是到处都可用,所以下面不使用。我们将使用stty -echo和stty echo代替。

注意:如果在函数中,下面所有bash变量都可以声明为局部变量,而不是不设置。

注意:perl在我尝试过的所有系统上都是可用的,因为它是许多东西的依赖项,而ruby和python不是,所以在这里使用perl。如果你能保证在ruby/python中执行此操作,你可以用它们的等价命令替换perl命令。

注意:在macOS 10.14.4上的bash 3.2.57中测试。其他shell /安装可能需要一些小的转换。


安全地提示用户输入要传递给curl的(可重用的)密码。如果需要多次调用curl,则特别有用。

对于现代shell, echo是内置的(检查通过哪个echo):

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input
echo ${pass} | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
unset username
unset pass

对于旧的shell, echo类似于/bin/echo(无论它所回显的是什么,都可以在进程列表中看到): 此版本不能重复使用密码,请参见下方。

url='https://example.com'
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
perl -e '
    my $val=<STDIN>;
    chomp $val;
    print STDERR "\n";  # we need to move the line ahead, but not send a newline down the pipe
    print $val;
' | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-
stty echo   # re-enable echoing user input
unset username


如果您碰巧需要将密码临时存储到一个文件中,以便在清除它之前为多个命令重用它(例如,因为您正在使用用于代码重用的函数,不想重复代码,并且不能通过echo传递值)。(是的,这种形式看起来有点不自然,它们不是不同库中的函数;我试图将它们减少到显示它所需的最小代码。)

当echo是内置的(这是特别人为的,因为echo是内置的,但提供了完整性):

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
read pass
echo "${pass}" > "${filepath}"
unset pass
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username

当echo类似于/bin/echo时:

url='https://example.com'
filepath="$(mktemp)"  # random path, only readable by current user
printf "Username: "
read username
printf "Password: "
stty -echo  # disables echoing user input, POSIX equivalent for 'read -s'
$(perl -e '
    my $val=<STDIN>;
    chomp $val;
    open(my $fh, ">", $ARGV[0]) or die "Could not open file \"$ARGV[0]\" $\!";
    print $fh $val;
    close $fh;
' "$filepath")
printf "\n" # we need to move the line ahead
stty echo   # re-enable echoing user input

cat "${filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-

rm "${filepath}"  # don't forget to delete the file when done!!
unset username

更安全的做法是:

curl --netrc-file my-password-file http://example.com

...由于在命令行上传递普通的用户/密码字符串,这是一个坏主意。

密码文件的格式为(按照man curl):

machine <example.com> login <username> password <password>

注意:

机器名不能包含https://或类似!只有主机名。 “machine”、“login”和“password”只是关键词;真正的信息是那些关键字之后的东西。

在我的例子中,我需要一个提示符,用户可以输入他们的凭据。

获得用户名和密码提示的最简单方法是以下一行代码:

read -p "Username: " U ; curl -u "$U" <URL> ; unset U

read命令提示输入用户名。-u "$U"参数告诉curl尝试使用用户名$U进行身份验证,并提示输入密码。

作为奖励,密码将只对curl可见,不会在任何日志或历史记录中结束。

curl的手册页有更多关于不同身份验证模式的详细信息: https://curl.se/docs/manpage.html

我也喜欢用户“iammyr”采用的方法。它可以涵盖cURL的身份验证算法失败的情况: https://stackoverflow.com/a/56130884/1239715

你可以使用gpg加密的netrc文件与curl像这样:

netrc_file="$HOME/netrc.gpg"
curl --netrc-file <(gpg -d $netrc_file) https://...

在某些API中它可能不起作用(比如rabbitmq)。

还有其他选择:

curl http://username:password@example.com

curl http://admin:123456@example.com

上面的格式也可以在浏览器中使用。