我正在运行SBT 1.2.8,我的项目需要从私有托管的Artifactory实例上的存储库中下载软件包。我的仓库受基本身份验证保护。阅读了大量示例和说明之后,我在我的仓库中创建了一个credentials.properties
文件。
realm=Artifactory Realm
host=artifactory.mycompany.com
username=my_username
password=my_password
然后我将以下内容添加到我的build.sbt
文件中
credentials += Credentials(new File("credentials.properties"))
然后我将存储库添加到resolvers.sbt
"My Company Artifactory" at "https://artifactory.mycompany.com/artifactory/my_private_repo/",
我构建了我的应用程序,并能够很好地下载受保护的程序包。
但是,我公司的系统管理员要求我打开Artifactory中的“隐藏未授权资源的存在”设置。当未经身份验证的用户尝试访问受保护的资源时,此设置将强制Artifactory返回404错误。通常在这种情况下,Artifactory返回带有WWW-Authenticate
标头的401s。
突然,我的应用程序无法解析其依赖项。我关闭了Artifactory设置,然后再次打开,并确认该设置实际上是导致我出现问题的原因。
除非SBT受到401和WWW-Authenticate
头(具有适当的域)的挑战,否则似乎不会发送凭据。查看SBT,Ivy和Coursier的文档和GitHub问题,似乎这种“抢先式身份验证”不受支持。
我花了很多时间试图以各种方式解决此问题,但找不到解决方案。这是我尝试过的:
https://my_username:my_password@artifactory.mycompany.com/artifactory/my_private_repo/
。这在我的浏览器和REST客户端中有效,但不适用于SBT。有人知道我如何让SBT使用抢占式HTTP基本身份验证吗?看来Maven和Gradle都支持此功能(请参阅下面的链接),但是我在SBT文档中找不到任何内容。
对抢占式身份验证的Maven支持:https://jfrog.com/knowledge-base/why-does-my-maven-builds-are-failing-with-a-404-error-when-hide-existence-of-unauthorized-resources-is-enabled/
对抢占式身份验证的分级支持: https://github.com/gradle/gradle/pull/386/files
我几乎要考虑设置一个本地代理以发送适当的标头Artifactory,并指出SBT将该本地代理用作解析器。但是,对于开发人员而言,这似乎不必要。
答案 0 :(得分:0)
你说得对。
您可以设置一个 AbstractRepository。参见 https://github.com/SupraFii/sbt-google-artifact-registry/blob/master/src/main/scala/ch/firsts/sbt/gar/ArtifactRegistryRepository.scala#L21 示例:
package ch.firsts.sbt.gar
import java.io.File
import java.util
import com.google.cloud.artifactregistry.wagon.ArtifactRegistryWagon
import org.apache.ivy.core.module.descriptor.Artifact
import org.apache.ivy.plugins.repository.AbstractRepository
import org.apache.maven.wagon.repository.Repository
class ArtifactRegistryRepository(repositoryUrl: String) extends AbstractRepository {
val repo = new Repository("google-artifact-registry", repositoryUrl)
val wagon = new ArtifactRegistryWagon()
override def getResource(source: String): ArtifactRegistryResource = {
val plainSource = stripRepository(source)
wagon.connect(repo)
ArtifactRegistryResource(repositoryUrl, plainSource, wagon.resourceExists(plainSource))
}
override def get(source: String, destination: File): Unit = {
val adjustedSource = if (destination.toString.endsWith("sha1"))
source + ".sha1"
else if (destination.toString.endsWith("md5"))
source + ".md5"
else
source
wagon.connect(repo)
wagon.get(adjustedSource, destination)
}
override def list(parent: String): util.List[String] = sys.error("Listing repository contents is not supported")
override def put(artifact: Artifact, source: File, destination: String, overwrite: Boolean): Unit = {
val plainDestination = stripRepository(destination)
wagon.connect(repo)
wagon.put(source, plainDestination)
}
private def stripRepository(fullName: String): String = fullName.substring(repositoryUrl.length + 1)
}