自定义Nexus的Maven仓库权限
需求背景
最近公司要搭建自己的Maven中央仓库,最终选择软件为Nexus OSS,但是遇到了一个问题,那就是我们希望根据已有的授权系统,自定义每个人是否有下载某个依赖的权限,基于这个需求最研究了一下Nexus,最终给了以下几个方案:
解决方案
方案1:业内有句话:没什么问题是加一层解决不了的,所以方案1就是让用户在maven的setting.xml中维护授权系统的用户密码,在服务端Nexus上加一层代理,来拦截用户的所有依赖下载请求,解析维护的用户密码再去授权系统鉴权,通过则放行,不通过则拦截。
方案2:基于Nexus的RBAC权限体系(权限-角色-用户体系),为每个项目创建不同的仓库,分配不同的角色,再根据需求创建用户分配角色。
优点:无需改造,使用已有的Nexus功能即可满足需求。
缺点:太麻烦,需要为每个项目创建仓库,用户和角色也要根据授权系统变化而变化,为了保证实时性,需要对接Nexus的RestApi接口来创建用户、角色等。
方案3:在RBAC的基础上使用Nexus的Selector功能,可以将所有项目都创建到一个仓库中,然后根据授权创建不同的selector过滤器分配给不同的用户,照比方案1,少了一步创建仓库的过程。
这里我们主要讲方案1,方案2和3相比1要开发对接的内容比较多,如果大家又其他更好的方案,请留言告诉我,十分感谢!
Demo实现
一句话总结:Maven配置setting中的sever的用户名密码最终会用base64加密放到请求头authorization中,所以我们拦截所有发送到Nexus的依赖下载请求,并重写authorization,将请求头中的信息用base64解密,得到用户名密码用于第三方鉴权,鉴权通过后再用正确Nexus用户名密码base64解密后替换原请求头中的authorization。
下面是具体的过程:
1,代理的选择:
我们已有的授权系统是基于Java开发的,所以在选择代理的时候,首选就是Java语言的,这里主要是验证可行性,所以本人在GitHub上随便找了个Java的代理项目方便验证。
2,Nexus搭建:
这一步网上很多,我们选择的版本是Nexus3 OSS,为了方便测试我用的docker-compose搭建,配置如下:
version: "2" services: nexus: restart: always image: sonatype/nexus3 container_name: nexus ports: - 8081:8081 volumes: - ./nexus/data:/nexus-data
3,重点实现
我在GitHub上找的Java的代理原理很简单,就是通过severlet重写请求信息,我在这里只是加了一个小小的改动,就是在重写请求头的拦截authorization,并且进行改写。
具体的代码可以查看项目:https://github.com/baisuper/nexusproxy
其中重点对authorization的解析和输出
private String[] authDecode(String authorizationValue) { String base64 = authorizationValue.substring(6); byte[] bytes = Base64.getDecoder().decode(base64); String[] auth = new String(bytes).split(":"); System.out.println("账号: " + auth[0]); System.out.println("密码: " + auth[1]); return auth; }
4,配置准备
启动本地的Nexus地址为:http://localhost:8081/
启动本地的代理项目,地址为:http://localhost:8080/
1,首先在Nexus中新建项目-角色-用户等,并上传一个测试的项目com.white.lean
新建的用户名和密码为:white-read/123qwe

2,接下来修改本地的Maven的setting.xml文件,随便写一个用户名和密码。

3,新建一个项目在pom依赖中添加white-read,仓库地址为http://localhost:8080

4,测试开始
首先不重写请求头中的authorization,按理说应该依赖下载会失败。
System.out.println("header = "+ headerName + "value =" + headerValue);
if (headerName.equals("authorization")) {
authDecode(headerValue);
// proxyRequest.addHeader(headerName, authEn("white-read", "123qwe"));
} else {
proxyRequest.addHeader(headerName, headerValue);
}

如预期一样,下载报错,同时在代理的日志中可以看到已经解析出了维护在setting中的用户名和密码:
接下来,放开的重写header的代码逻辑,再测试下载,可以看到下载成功了:
![]()
写在最后
如果你没有耐心看完上面的过程,请看Demo章节下的一句话红字总结。
至此Demo就告一段落了,当然后续如果要在生产中使用还有很多工作要做,但是作为一个demo应该够了,后续的修改和优化方向,我想了以下:
1,无法通过代理地址直接访问Nexus,会有一些资源被拦拦截,不过后续可以换其他代理,比如nginx等,所以这个就没去管。
2,其他代理选择,可以尝试nginx,netty等。
3,鉴权补完:目前只拿到了用户密码,没有实际进行鉴权操作。
4,密码加密的情况:使用maven的master密码加密维护,这个还没测试,后面有时间测试,猜想这个不会有影响,只是本地存储进行加密而已。

浙公网安备 33010602011771号