我想访问一个需要用户名/密码的URL。我想用curl访问它。现在我正在做的事情是:
curl http://api.somesite.com/test/blah?something=123
我得到一个错误。我想我需要在上面的命令中指定用户名和密码。
我该怎么做呢?
我想访问一个需要用户名/密码的URL。我想用curl访问它。现在我正在做的事情是:
curl http://api.somesite.com/test/blah?something=123
我得到一个错误。我想我需要在上面的命令中指定用户名和密码。
我该怎么做呢?
当前回答
我在bash (Ubuntu 16.04 LTS)中有同样的需求,答案中提供的命令在我的情况下无法工作。我不得不使用:
curl -X POST -F 'username="$USER"' -F 'password="$PASS"' "http://api.somesite.com/test/blah?something=123"
-F参数中的双引号仅在使用变量时才需要,因此从命令行…-F 'username=myuser'…会没事的。
相关安全注意:正如Mark Ribau先生在注释中指出的那样,此命令在进程列表中显示密码($PASS变量,展开)!
其他回答
这比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”只是关键词;真正的信息是那些关键字之后的东西。
向curl传递凭据最安全的方法是提示插入凭据。这是在传递前面建议的用户名(-u username)时发生的情况。
但是如果不能通过这种方式传递用户名呢? 例如,用户名可能需要是url的一部分,而只有密码是json有效负载的一部分。
tl;博士: 下面是在这种情况下如何安全地使用curl:
read -p "Username: " U; read -sp "Password: " P; curl --request POST -d "{\"password\":\"${P}\"}" https://example.com/login/${U}; unset P U
Read将提示从命令行输入用户名和密码,并将提交的值存储在两个变量中,以便在后续命令中引用并最终取消设置。
我将详细说明为什么其他解决方案都不理想。
为什么环境变量不安全
Access and exposure mode of the content of an environment variable, can not be tracked (ps -eww ) since the environment is implicitly available to a process Often apps grab the whole environment and log it for debugging or monitoring purposes (sometimes on log files plaintext on disk, especially after an app crashes) Environment variables are passed down to child processes (therefore breaking the principle of least privilege) Maintaining them is an issue: new engineers don't know they are there, and are not aware of requirements around them - e.g., not to pass them to sub-processes - since they're not enforced or documented.
为什么直接在命令行中输入它是不安全的 因为运行ps -aux的任何其他用户最终都可以看到您的秘密,因为它列出了为每个当前运行的进程提交的命令。 这还因为您的秘密最终会出现在bash历史记录中(一旦shell终止)。
为什么在本地文件中包含它是不安全的 对文件的严格POSIX访问限制可以降低这种情况下的风险。但是,它仍然是文件系统上的一个未加密的文件。
我在bash (Ubuntu 16.04 LTS)中有同样的需求,答案中提供的命令在我的情况下无法工作。我不得不使用:
curl -X POST -F 'username="$USER"' -F 'password="$PASS"' "http://api.somesite.com/test/blah?something=123"
-F参数中的双引号仅在使用变量时才需要,因此从命令行…-F 'username=myuser'…会没事的。
相关安全注意:正如Mark Ribau先生在注释中指出的那样,此命令在进程列表中显示密码($PASS变量,展开)!
其他回答建议netrc指定用户名和密码,根据我所读到的,我同意。下面是一些语法细节:
https://ec.haxx.se/usingcurl-netrc.html
和其他回答一样,我想在这个问题上强调,要注意安全。
虽然我不是专家,但我发现这些链接很有见地:
https://ec.haxx.se/cmdline-passwords.html
总结:
使用加密版本的协议(HTTPS vs HTTP) (FTPS vs FTP)可以帮助避免网络泄漏。
使用netrc可以帮助避免命令行泄漏。
更进一步,似乎还可以使用gpg加密netrc文件
https://brandur.org/fragments/gpg-curl
这样,您的凭据就不会“静止”(存储为纯文本)。