扩展Nacos使其支持https和登陆 拉取配置 com.alibaba.nacos.client.naming.tls.enable

官方依赖版本:

nacos-server :1.2.1nacos-config-spring-boot.version :0.2.7
nacos server支持启用鉴权### If turn on auth system:nacos.core.auth.enabled=true

按照官方example( https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-config-example )配置好 发现客户端连接不上,总是403的错误,根据惯例来讲,这是没有授权引起的,然后我去github上找了下,果然有人提了这个 
issue
 
  问题有了,那么接下来追踪产生的原因。   跟踪源码发现 login 方法调用HttpClient 而 nacos server的数据接口是用ServerHttpAgent->HttpSimpleClient ,都是对HttpConnection的包装,但内部url拼接规则不同
  由于这里拼接了“/”,导致 nacos上下文配置拼接时路径变成了//

nacos.config.context-path=/nacos

nacos server端使用了spring security进行权限,在新版的spring security中,对url进行了规则强校验,不允许类似“http://127.0.0.1//xxx”这种"//“出现,导致出现获取配置出现500的错误。(如果设置nacos.config.context-path=nacos 又会导致登陆失败,拿不到accessToken)   所以如果要不该源码实现 登陆权限 拉取配置需要 通过代理转换请求地址。 于是在nacos server端配置nginx 代理请求
  在访问nacos前加入一层nginx location / {           proxy_pass http://127.0.0.1:8848/;         }     location /n/nacos {           proxy_pass http://127.0.0.1:8848/nacos/;         } 这样做的目的是为了重写”//“为”/",保证security的url校验能够成功, 其中 nacosserver是nacos的访问url,这里我配置了两个,第一个是访问nacos的管理界面,第二个是client注册nacos的url   这样登陆授权是满足了,http明文传输配置中心的密码等敏感信息还是不够安全,所以扩展nacos使其支持https就是问题了 由于ServerHttpAgent类源码写死了 isSSL=false,看来不该源码不行了。(本来想替换ClientWorker的agent实例,结果发现是 NacosConfigService New出来的,和Spring框架设计上的差距有点大啊————)   好吧,源码开撸>>>> 修改ServerHttpAgent

private String getUrl(String serverAddr, String relativePath,boolean isSSL) { String contextPath = serverListMgr.getContentPath().startsWith("/") ? serverListMgr.getContentPath() : "/" + serverListMgr.getContentPath(); String url= StringUtils.removeEnd(serverAddr,"/")+"/"+StringUtils.removeStart(contextPath,"/")+ relativePath; if (isSSL &&url.startsWith(httpPre)){ return httpsPre+StringUtils.removeStart(url,httpPre); }else{ return url; }}

SecurityProxy.java

if (HttpClient.ENABLE_HTTPS){ url = "https://" + server + contextPath + LOGIN_URL;}else { url = "http://" + server + contextPath + LOGIN_URL;}if (server.contains(Constants.HTTP_PREFIX)||server.contains(Constants.HTTPS_PREFIX)) { url = server + contextPath + LOGIN_URL;}

为了避免证书 校验 请求域名的问题 对HttpConnection所在类做了以下处理

static { try { trustAllHttpsCertificates(); HttpsURLConnection.setDefaultHostnameVerifier( (urlHostName, session) -> true ); } catch (Exception e) { }}private static void trustAllHttpsCertificates() throws NoSuchAlgorithmException, KeyManagementException { TrustManager[] trustAllCerts = new TrustManager[1]; trustAllCerts[0] = new TrustAllManager(); SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory( sc.getSocketFactory());}private static class TrustAllManager implements X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] certs, String authType) { } public void checkClientTrusted(X509Certificate[] certs, String authType) { }}

为了避免配置过于杂乱,对于是否启用ssl依然复用 这个属性

com.alibaba.nacos.client.naming.tls.enable

启动类加System.setProperty("com.alibaba.nacos.client.naming.tls.enable","true")或者  启动命令加-Dcom.alibaba.nacos.client.naming.tls.enable   完整代码参见我的github  https://github.com/huawenyao/nacos ,欢迎start~   关键源码 ServerHttpAgent.httpGet private String getUrl(String serverAddr, String relativePath) { return serverAddr + "/" + serverListMgr.getContentPath() + relativePath; }   public NacosConfigService(Properties properties) throws NacosException { String encodeTmp = properties.getProperty(PropertyKeyConst.
ENCODE); if (StringUtils.
isBlank(encodeTmp)) { encode = Constants.
ENCODE; } else { encode = encodeTmp.trim(); } initNamespace(properties); agent = new MetricsHttpAgent(new ServerHttpAgent(properties)); agent.start(); worker = new ClientWorker(agent, configFilterChainManager, properties); }

 

  推荐:
vi设计公司

相关文章