自定义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密码加密维护,这个还没测试,后面有时间测试,猜想这个不会有影响,只是本地存储进行加密而已。

 

posted @ 2020-07-19 21:10  8号位  Views(895)  Comments(0)    收藏  举报