SBT:发布到公司Nexus仓库未授权

22

快速解决

所需的凭据需要与Nexus定义的确切领域相匹配。请参见下面的说明,了解您已定义的内容,但最肯定是“Sonatype Nexus Repository Manager”。将其余详细信息添加到凭据中,就像平常一样。

c:/data/user/.sbt/.credentials

realm=Sonatype Nexus Repository Manager
host=nexus
user=repouser
password=password

build.sbt credentials += Credentials(Path.userHome / ".sbt" / ".credentials")

构建文件.sbt 添加凭据:+= 凭据(Path.userHome / ".sbt" / ".credentials")

publishTo <<= version { v: String =>
  val nexus = "http://nexus/" 
  if (v.trim.endsWith("SNAPSHOT"))
    Some("snapshots" at nexus + "content/repositories/libs-snapshots")
  else
    Some("releases" at nexus + "content/repositories/libs-releases")
  }

问题

我正在尝试将一个jar发布到企业nexus仓库。

我可以通过Maven成功地完成这个过程,并且已经配置了仓库,以便能够使用Nexus提供内部jar。但是,由于授权问题,发布失败了。

> publish
[info] Packaging c:\app\target\scala-2.10\app_2.10-0.1-sources.jar ...
[info] Wrote D:\app\target\scala-2.10\app_2.10-0.1.pom
[info] :: delivering :: com.app#app_2.10;0.1 :: 0.1 :: release :: Tue May 07 18:28:44 BST     2013
[info] Done packaging.
[info]  delivering ivy file to D:\app\target\scala-2.10\ivy-0.1.xml
[info] Packaging D:\app\target\scala-2.10\app_2.10-0.1.jar ...
[info] Done packaging.
[trace] Stack trace suppressed: run last *:publish for the full output.
[error] (*:publish) java.io.IOException: Access to URL http://nexus/content/groups/common/com/app/app_2.10/0.1/app_2.10-0.1.pom was refused by the server: Unauthorized

c:/data/user/.sbt/.credentials

realm=X 
host=nexus
user=repouser
password=password

c:/data/user/.sbt/repositories

 [repositories]
  local
  x-repo: http://nexus/content/groups/common
  typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/,     [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext]   
  sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/
  maven-central

app/build.sbt

 name := "app"

 organization := "com.app"

 version := "0.1"

 scalaVersion := "2.10.1"

 libraryDependencies ++= Seq(
"org.scalatest" % "scalatest_2.10" % "2.0.M5b" % "test"
 )

 EclipseKeys.withSource := true

 publishMavenStyle := true

 credentials += Credentials(Path.userHome / ".sbt" / ".credentials")

 publishTo := Some("X Maven Repo" at "http://nexus/content/groups/common")

我的Maven settings.xml
 <mirrors>
 <mirror>
  <id>x-repo</id>
  <name>X Maven repo</name>
      <url>http://nexus/content/groups/common</url>
  <mirrorOf>*</mirrorOf>
 </mirror>
 </mirrors>

 <servers>
     <server>
       <id>x-repo</id>
       <username>repouser</username>
       <password>password</password>
     </server>
   </servers>

我已经按照官方文档和其他一些文章的指导进行了尝试,包括StackOverflow上的这篇文章或邮件列表中的这个。但是都没有起作用。我已经尝试启用额外的日志记录,但没有提供更多详细信息。
我可以使用以下命令手动部署到maven:
 mvn deploy:deploy-file -Durl=http://nexus/content/repositories/libs-snapshots -DrepositoryId=x-repo -DgroupId=com.app -DartifactId=app -Dpackaging=jar -Dversion=0.1-SNAPSHOT -Dfile=D:\app\target\scala-2.10\app_2.10-0.1.jar

尝试使用以下publishTo,但仍没有成功。
publishTo <<= version { v: String =>
  val nexus = "http://nexus/" 
  if (v.trim.endsWith("SNAPSHOT"))
    Some("snapshots" at nexus + "content/repositories/libs-snapshots")
  else
    Some("releases" at nexus + "content/repositories/libs-releases")
  }

这些命令在需要授权时运行失败。

凭据中的领域,它对应于maven中的服务器存储库ID还是名称?无论哪种方式都不起作用。

我一直在尝试为Ivy启用更多日志记录,但无法获得更多详细信息。

set ivyLoggingLevel := UpdateLogging.Full

根据这个,应该有进一步的日志记录:

https://svn.apache.org/repos/asf/ant/ivy/core/tags/2.2.0/src/java/org/apache/ivy/util/url/IvyAuthenticator.java

我在公司内部代理后面,需要设置HTTP和HTTPS的用户名和密码。也许是这个导致了阻塞?

有什么建议可以提高常春藤日志级别吗?


更新

我已经找到了一个解决方法,使用sbt-aether-deploy插件,它使用Maven基础设施(wagon)进行部署。

凭据完全相同。实际上,领域似乎并不重要。

以下是使用的行:

    credentials += Credentials(Path.userHome / ".sbt" / ".credentials")

publishTo <<= version { v: String =>
  val nexus = "http://nexus/"
    if (v.trim.endsWith("SNAPSHOT"))
    Some("snapshots" at nexus + "content/repositories/libs-snapshots")
  else 
    Some("releases" at nexus + "content/repositories/libs-releases")
}

seq(aetherSettings: _*)

seq(aetherPublishSettings: _*)

代理、ivy和nexus之间存在问题。

我仍然对使用ivy有兴趣,欢迎提出建议。


进一步更新:
使用
curl -X POST http://nexusUser:nexusPassword@nexus/content/repositories/libs-snapshots -v

我能够连接到服务器。
指定代理并得到相同结果(已配置为跳过本地网络,但某些Java进程例如SBT需要头)。
当未指定nexusUser:nexusPassword时,我收到以下标头:
WWW-Authenticate: BASIC realm="Sonatype Nexus Repository Manager"
实际上这就是问题所在,凭据需要的领域名称必须是该确切标题,而不是像Maven定义的其他自定义存储库名称。
非常感谢!
2个回答

24

Ivy使用WWW-Authenticate头域,该域必须与您的凭据文件中配置的相等,并且要逐字节匹配。

sbt-aether-deploy也使用相同的头域,但使用Aether作为其部署机制。Ivy则不然。

确定WWW-Authenticate头域的最简单方法是使用cURL。

curl -X POST http://nexus/content/repositories/libs-snapshots -v > /dev/null

cURL会提示您输入用户名和密码。

-v将增加详细程度,因此您将能够查看请求和响应的标头。


6
这里需要注意的是,在凭证文件中,主机名只需填写 Nexus 服务器的 IP 地址或域名,如果还包含端口号,则凭证将无法生效。 - Cristian Vrabie

3
我猜测您的凭证文件路径可能不正确。请尝试更改为以下内容:
credentials += Credentials(Path.userHome / ".sbt" / ".credentials")

转换为:

credentials += Credentials("c:/data/user/.sbt/.credentials")

或者直接尝试故障排除:

credentials += Credentials("Sonatype Nexus Repository Manager", 
  "nexus.scala-tools.org", "admin", "admin123") 

如果这些方法都不起作用,请检查您的凭据是否有效。

4
我尝试了在文件中直接编写路径或使用凭据,但仍然无法运行。 - fracca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接