我想访问需要用户名/密码的 URL。我想尝试使用 curl 访问它。现在我正在做类似的事情:
curl http://api.somesite.com/test/blah?something=123
我得到一个错误。我想我需要在上面的命令中指定用户名和密码。
我怎样才能做到这一点?
使用 -u
标志包含用户名,curl 将提示输入密码:
curl -u username http://example.com
您还可以在命令中包含密码,但是您的密码将在 bash 历史记录中可见:
curl -u username:password http://example.com
这样做更安全:
curl --netrc-file my-password-file http://example.com
...在命令行上传递一个普通的用户/密码字符串是一个坏主意。
密码文件的格式是(根据 man curl
):
machine <example.com> login <username> password <password>
笔记:
机器名称不得包含 https:// 或类似名称!只是主机名。 “机器”、“登录”和“密码”这些词只是关键字;实际信息是那些关键字之后的东西。
-K <file>
或 --config <file>
通过文件或标准输入接收 curl 标志。 (警告:不要与 -k
或 --insecure
混淆!)
.netrc
文件要好得多,因此只有 your 用户可以读取它,而不是其他允许 的机制(例如命令行参数)其他 用户阅读信息。
或相同的东西但语法不同
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-
。我必须将 -K-
放在旧 macOS bash YMMV 的 url 之前。
echo "-u user:$(cat passwordfile)"|curl -K- url
通常 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 与 HTTP)(FTPS 与 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 点,此命令在进程列表中显示密码($PASS 变量,展开)!
curl: option -F: is badly used here
。卷曲 7.58。你的版本是什么?
您可以使用类似的命令,
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 命令如下:
curl -Lk -XGET -u "${API_USER}:${API_HASH}" -b cookies.txt -c cookies.txt -- "http://api.somesite.com/test/blah?something=123"
然后将调用您的 restful api 并传递带有 API_USER
和 API_HASH
的 Base64 编码值的 http WWW_Authentication
标头。 -Lk
只是告诉 curl 遵循 http 30x 重定向并使用不安全的 tls 处理(即忽略 ssl 错误)。而双 --
只是停止处理命令行标志的 bash 语法糖。此外,-b cookies.txt
和 -c cookies.txt
标志通过 -b
发送 cookie 和 -c
在本地存储 cookie 来处理 cookie。
该手册有更多examples of authentication方法。
将凭据传递给 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 -eww),因为环境对进程隐式可用 通常应用程序会抓取整个环境并将其记录下来以用于调试或监视目的(有时在日志文件中以明文形式显示)在磁盘上,特别是在应用程序崩溃后)环境变量被传递给子进程(因此打破了最小特权原则)维护它们是一个问题:新工程师不知道它们在那里,也不知道周围的需求- 例如,不要将它们传递给子流程 - 因为它们没有被强制执行或记录。
为什么直接在命令行中将其键入命令是不安全的因为您的密钥最终会被运行 ps -aux
的任何其他用户看到,因为它列出了为每个当前运行的进程提交的命令。还因为您的 secrte 最终会出现在 bash 历史记录中(一旦 shell 终止)。
为什么将其包含在本地文件中不安全 对文件的严格 POSIX 访问限制可以减轻这种情况下的风险。但是,它仍然是您文件系统上的一个文件,在静止时未加密。
在某些 API 中它可能不起作用(如 rabbitmq)。
有替代方案:
curl http://username:password@example.com
curl http://admin:123456@example.com
上述格式也可在浏览器中使用。
您可以像这样使用带有 curl 的 gpg 加密 netrc 文件:
netrc_file="$HOME/netrc.gpg"
curl --netrc-file <(gpg -d $netrc_file) https://...
这比 OP 要求的要多得多,但由于这是安全地将密码传递给 curl
的最佳结果,因此我在此处为其他到达此处搜索的人添加了这些解决方案。
注意:read
命令的 -s
arg 不是 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
就我而言,我需要一个提示,用户可以在其中输入他们的凭据。
获取用户名和密码提示的最简单方法是以下单行:
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
如果您的服务器支持 Basic
身份验证,您可以执行以下操作:
printf 'header="Authorization: Basic %s"' "$(base64 --wrap=0 credentials)"|
curl --config - https://example.org
credentials
将是您以 username:password
形式存储用户名和密码的文件。
此解决方案的好处:
无需转义特殊字符
适用于任何密码,即使它包含空格、引号、反斜杠或其他特殊字符,因此它也可以在您不控制输入的脚本中安全使用
在带有内置 printf 的 shell 中,登录数据不会显示在进程列表中
如果您的 shell 没有 printf
作为内置命令,您可以执行以下操作以避免登录数据出现在进程列表中:
{ printf 'header="Authorization: Basic '; base64 --wrap=0 credentials; printf '"'; }|
curl --config - https://example.org
您应该确定什么是身份验证类型。
如果是摘要认证,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
选项吗?
print -- '-u username:password' > somewhere && curl -K somewhere http://...
--netrc-file
)更安全。它将密码排除在历史记录、ps、您的脚本等之外。这是我在所有脚本中使用的唯一形式以及curl
的所有经过身份验证的用法。