0

我正在运行 SBT 1.2.8,我的项目需要从私有托管的 Artifactory 实例上的 repo 下载包。我的仓库受基本身份验证保护。在阅读了大量示例和说明后,我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标头的 401。

突然,我的应用程序无法解决其依赖关系。我关闭了 Artifactory 设置,然后再次打开,并验证此设置实际上是我的问题的原因。

似乎 SBT 不会发送凭据,除非它受到 401 和WWW-Authenticate标头(具有正确的领域)的挑战。查看 SBT、Ivy 和 Coursier 的文档和 GitHub 问题,似乎这种“抢先式身份验证”不是受支持的功能。

我花了很多时间试图以各种方式解决这个问题,但我找不到解决方案。这是我尝试过的:

  • 将我的 Artifactory 用户名和密码添加到存储库 url,看起来像https://my_username:my_password@artifactory.mycompany.com/artifactory/my_private_repo/. 这适用于我的浏览器和 REST 客户端,但不适用于 SBT。
  • 从我的凭证文件中省略“领域”
  • 切换到 SBT 1.3.9 并使用新版本尝试上述所有内容。

有谁知道我如何让 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-资源启用/

Gradle 对抢占式身份验证的支持: https ://github.com/gradle/gradle/pull/386/files

我几乎在考虑设置一个本地代理来发送正确的标头 Artifactory,并指向 SBT 使用本地代理作为解析器。但是,对于开发人员来说,这似乎是不必要的麻烦。

4

1 回答 1

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)

}
于 2021-03-07T07:07:42.017 回答