【发布时间】:2011-02-05 09:31:36
【问题描述】:
我想访问需要用户名/密码的 URL。我想尝试使用 curl 访问它。现在我正在做类似的事情:
curl http://api.somesite.com/test/blah?something=123
我得到一个错误。我想我需要在上面的命令中指定用户名和密码。
我该怎么做?
【问题讨论】:
标签: curl credentials
我想访问需要用户名/密码的 URL。我想尝试使用 curl 访问它。现在我正在做类似的事情:
curl http://api.somesite.com/test/blah?something=123
我得到一个错误。我想我需要在上面的命令中指定用户名和密码。
我该怎么做?
【问题讨论】:
标签: curl credentials
使用-u 标志包含用户名,curl 将提示输入密码:
curl -u username http://example.com
您也可以在命令中包含密码,但是您的密码将在 bash 历史记录中可见:
curl -u username:password http://example.com
【讨论】:
print -- '-u username:password' > somewhere && curl -K somewhere http://...
--netrc-file)更安全。它将密码排除在历史记录、ps、您的脚本等之外。这是我在所有脚本中使用的唯一形式以及curl 的所有经过身份验证的用法。
这样做更安全:
curl --netrc-file my-password-file http://example.com
...在命令行上传递一个普通的用户/密码字符串是个坏主意。
密码文件的格式为(按照man curl):
machine <example.com> login <username> password <password>
注意:
https:// 或类似名称!只是主机名。machine”、“login”和“password”这些词只是关键字;实际信息是这些关键字之后的内容。【讨论】:
-K <file> 或--config <file> 通过文件或标准输入接收 curl 标志。 (警告:不要与-k 或--insecure 混淆!)
.netrc 文件要好得多,因此只有 your 用户可以阅读它,而不是其他机制(例如命令line args) 让其他用户阅读信息。
或相同的东西但语法不同
curl http://username:password@api.somesite.com/test/blah?something=123
【讨论】:
start "" "http://username:password@api.somesite.com/test/blah?something=123"。它可以从任何地方启动。这也适用于 ftp 登录;D
-u 参数,它不会显示在进程列表中。 curl的巧妙技巧:-)。见How does curl protect a password from appearing in ps output?
您也可以直接发送用户名:
curl -u USERNAME http://server.example
Curl 然后会要求您输入密码,并且密码不会在屏幕上显示(或者如果您需要复制/粘贴命令)。
【讨论】:
要在脚本中安全地传递密码(即防止它出现在 ps auxf 或日志中),您可以使用 -K- 标志(从标准输入读取配置)和 heredoc:
curl --url url -K- <<< "--user user:password"
【讨论】:
--config 选项 (-K) 的引用...可能更好的解决方案是将“--user user:password”放入文件中,然后简单地 -K the file 所以您只有一份密码副本,而不是每个脚本中的副本。保护单个文件要容易得多。
cat "${password_filepath}" | sed -e "s/^/-u ${username}:/" | curl --url "${url}" -K-。我必须在旧 macOS bash YMMV 的 url 之前加上 -K-。
通常CURL命令引用为
curl https://example.com\?param\=ParamValue -u USERNAME:PASSWORD
如果您没有任何密码或想跳过命令提示符要求输入密码,请将密码部分留空。
即curl https://example.com\?param\=ParamValue -u USERNAME:
【讨论】:
curl -X GET -u username:password {{ http://www.example.com/filename.txt }} -O
【讨论】:
很简单,请执行以下操作:
curl -X GET/POST/PUT <URL> -u username:password
【讨论】:
其他答案建议 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
这样,您的凭据就不会“静止”(存储)为纯文本。
【讨论】:
为了让密码至少不会在你的.bash_history中弹出:
curl -u user:$(cat .password-file) http://example-domain.tld
【讨论】:
ps auxw |grep curl 的人可以看到它。同样,如果通过sudo运行,密码将被记录下来
我在 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' ... 就可以了。
相关安全注意事项:Mr. Mark Ribau 指向 cmets 此命令在进程列表中显示密码($PASS 变量,展开)!
【讨论】:
curl: option -F: is badly used here。卷曲 7.58。你的版本是什么?
简单地说,最安全的方法是使用环境变量来存储/检索您的凭据。因此 curl 命令如下:
curl -Lk -XGET -u "${API_USER}:${API_HASH}" -b cookies.txt -c cookies.txt -- "http://api.somesite.com/test/blah?something=123"
然后将调用您的 RESTful api 并传递带有 Base64 编码值 API_USER 和 API_HASH 的 http WWW_Authentication 标头。 -Lk 只是告诉 curl 遵循 http 30x 重定向并使用不安全的 tls 处理(即忽略 ssl 错误)。而双 -- 只是用于停止处理命令行标志的 bash 语法糖。此外,-b cookies.txt 和 -c cookies.txt 标志处理 cookie,-b 发送 cookie,-c 在本地存储 cookie。
手册中有更多examples of authentication方法。
【讨论】:
你可以使用类似的命令,
curl -u user-name -p http://www.example.com/path-to-file/file-name.ext > new-file-name.ext
然后会触发HTTP密码。
参考: http://www.asempt.com/article/how-use-curl-http-password-protected-site
【讨论】:
将凭据传递给 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 会在命令行提示输入用户名和密码,并将提交的值存储在两个变量中,这些变量可以在后续命令中引用并最终取消设置。
我将详细说明为什么其他解决方案不理想。
为什么环境变量不安全
为什么直接在命令行输入命令不安全
因为您的秘密最终会被运行ps -aux 的任何其他用户看到,因为它列出了为每个当前运行的进程提交的命令。
还因为您的 secrte 最终会出现在 bash 历史记录中(一旦 shell 终止)。
为什么将其包含在本地文件中是不安全的 对文件进行严格的 POSIX 访问限制可以降低这种情况下的风险。但是,它仍然是您文件系统上的一个文件,在静止时未加密。
【讨论】:
在某些 API 中可能不起作用(例如 rabbitmq)。
还有其他选择:
curl http://username:password@example.com
curl http://admin:123456@example.com
上述格式也可以在浏览器中使用。
【讨论】:
这比 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 中测试。其他外壳/安装可能需要一些小的翻译。
安全地提示用户输入(可重复使用的)密码以传递给 curl。如果您需要多次调用 curl,则特别有用。
对于现代 shell,echo 是内置的(通过 which 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
【讨论】:
如果您使用的是具有 Gnome 密钥环应用程序的系统,避免直接暴露密码的解决方案是使用 gkeyring.py 从密钥环中提取密码:
server=server.example.com
file=path/to/my/file
user=my_user_name
pass=$(gkeyring.py -k login -tnetwork -p user=$user,server=$server -1)
curl -u $user:$pass ftps://$server/$file -O
【讨论】:
您可以像这样使用带有 curl 的 gpg 加密 netrc 文件:
netrc_file="$HOME/netrc.gpg"
curl --netrc-file <(gpg -d $netrc_file) https://...
【讨论】:
您应该确定身份验证类型是什么。
如果是摘要认证,http头是:
GET /xxxxxxxxxxx HTTP/1.1
Host: 192.168.3.142
User-Agent: Go-http-client/1.1
Authorization: Digest username="admin", realm="admin@51200304-49-test", nonce="5.1722929000077545", uri="/xxxxxxxxxxx", response="52d30eba90820f2c4fa4d3292a4a7bbc", cnonce="f11900fe0906e3899e0cc431146512bb", qop=auth, nc=00000001
Accept-Encoding: gzip
您可以使用--digest 选项:
curl --digest -u 'username:password' 'http://xxxxxxxxxxx'
【讨论】:
--digest 选项吗?