主要说说当项目中的某些依赖需要使用http协议的git项目地址作为依赖下载地址时,如何进行免交互认证的问题,因为使用ssh的话肯定都是已经配置好ssh key了。
当使用http协议拉取git项目时,是需要用户名和密码的,默认情况下,如果在系统中曾经拉取过某个项目并且输入过用户名和密码,那么用户凭证会被存储,在windows系统中可以在凭据管理器中查看到,而在类unix系统下则是存储在~/.git-credentials
文件中,以项目的服务器地址作为区分。在以后拉取相同服务器上的项目时会查找匹配的条目就不用再次输入了。
windows系统下:
linux系统下:
但是在我们项目中安装依赖时,由于使用的非交互式终端来执行git命令,所以如果系统没有对应的凭证,那么下载就会失败
报错信息如下形式:
如何解决
最简单的当然是直接http url中明文携带用户名跟密码, 即http://username:password@a.b.com
这种形式,但是在安全性上则会有一点风险。
主要说另外一种解决方案:
在使用git拉取项目时,如果没有在凭证存储中找到任何匹配的答案,则会发起问询,策略如下:
- If the
GIT_ASKPASS
environment variable is set, the program specified by the variable is invoked. A suitable prompt is provided to the program on the command line, and the user’s input is read from its standard output. - Otherwise, if the
core.askPass
configuration variable is set, its value is used as above. - Otherwise, if the
SSH_ASKPASS
environment variable is set, its value is used as above. - Otherwise, the user is prompted on the terminal.
即首先查找环境变量中GIT_ASKPASS
变量,如果有则调用该变量指定的程序,如果没有此变量,则查看git core中配置的askPass
变量,使用方式同上,如果core.askPass
也没有,则查找环境变量中的SSH_ASKPASS
变量,使用方式同上,最后,如果以上变量查找都失败了,则在终端中弹出提示。
以上的变量值都需要指向一个可执行文件的地址。
所以需要在执行npm install
命令的时候提供一个环境变量就可以了。
在调用以上变量指向的可执行文件时,会带有参数,并且询问用户和询问密码时会每次都调用这个可执行文件,执行时命令调用如下:
询问用户名:
$GIT_ASKPASS "Username for ..."
询问密码:
$GIT_ASKPASS "Password for ..."
所以可执行文件应该这么写:
#!/bin/bash
case "$1" in
Username*) exec echo "your username" ;;
Password*) exec echo "your password" ;;
esac
这样的话就可以在没有用户凭证的情况下免交互输入username与password,避免安装依赖失败。
一般在自己电脑上都是存储有对应项目的凭证的,主要是为了解决在CI/CD任务中出现的此类错误,在自动化脚本中可以这么写:
先创建一个临时文件且修改权限为可执行文件并赋值给GIT_ASKPASS
变量,然后将上述shell脚本写入临时文件中即可。
以jenkins配置的脚本为例:
# 设置变量
GIT_ASKPASS=$(mktemp) && chmod a+rx $GIT_ASKPASS && export GIT_ASKPASS
cat > $GIT_ASKPASS <<< '#!/bin/bash
case "$1" in
Username*) exec echo "$JENKINS_CREDENTIALS_USR" ;;
Password*) exec echo "$JENKINS_CREDENTIALS_PSW" ;;
esac
'
# 安装依赖
npm install
这样的话即可成功安装git项目作为依赖了。