尝到了maven带给项目工程轻量级体验,终究还是吃了maven的隐藏苦果~

渊源:

最近,我的maven项目突然获取新的jar包,获取不到。看了本地仓库,发现下载的竟然是.lastUpdated文件。然后,由于项目紧急,仓促百度,网上很多的解决办法是,删除.lastUpdated文件,重新maven获取。

结果,不论删除多少次,最终下载的还是后缀为.lastUpdated的文件。当时的我内心焦灼。

问题定位:

冷静,莫慌!总得知其然吧。

因为我是用的idea编译器,我想到了去跟踪idea.log日志(路径:单击【Help】按钮,在弹出的下拉菜单中单击【Show Log in Explorer】) ,一步一步查找报错!最终,找到了比较有用的日志报错信息

查看maven的配置 查看maven日志_查看maven的配置

欣喜的自己以为找到了问题的根源,十分开心。但是,一旁的同事出于好心帮助,对比了我和他的pom文件,以及maven的settings配置,发现基本一致。但是,我确实出现了问题,于是根据日志的报错信息。去百度,更深意义的定位问题。

最终,找到了

《解决异常:sun.security.provider.certpath.SunCertPathBuilderException》博客:


问题分析:

首先阿里云的私服路径 http://maven.aliyun.com/nexus/content/groups/public/,与本地的maven之间存在访问认证。
所以,需要使用https的认证访问,而使用 ssl 连接时,遇到不信任的证书,应用程序一般都会拒绝连接。
浏览网站时,我们可以通过在浏览器的设置中导入证书,把证书加入到信任列表中。
而在 JAVA 直接进行 SSL 连接应用时,默认没有一个界面来导入证书。JAVA 进行不信任的 ssl 连接时,会报如下异常:
这时候,就要找到一种方式,在 JAVA 的运行环境中导入信任证书。

问题解决:

就是在给本地java运行环境 jre,配置相应的证书。

1、首先我在D盘根目录下,创建InstallCert.java文本;内容如下

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.security.KeyStore;

import java.security.MessageDigest;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLException;

import javax.net.ssl.SSLSocket;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManager;

import javax.net.ssl.TrustManagerFactory;

import javax.net.ssl.X509TrustManager;



public class InstallCert {



public static void main(String[] args) throws Exception {

String host;

int port;

char[] passphrase;

if ((args.length == 1) || (args.length == 2)) {

String[] c = args[0].split(":");

host = c[0];

port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);

String p = (args.length == 1) ? "changeit" : args[1];

passphrase = p.toCharArray();

} else {

System.out

.println("Usage: java InstallCert <host>[:port] [passphrase]");

return;

}



File file = new File("jssecacerts");

if (file.isFile() == false) {

char SEP = File.separatorChar;

File dir = new File(System.getProperty("java.home") + SEP + "lib"

+ SEP + "security");

file = new File(dir, "jssecacerts");

if (file.isFile() == false) {

file = new File(dir, "cacerts");

}

}

System.out.println("Loading KeyStore " + file + "...");

InputStream in = new FileInputStream(file);

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

ks.load(in, passphrase);

in.close();



SSLContext context = SSLContext.getInstance("TLS");

TrustManagerFactory tmf = TrustManagerFactory

.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(ks);

X509TrustManager defaultTrustManager = (X509TrustManager) tmf

.getTrustManagers()[0];

SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

context.init(null, new TrustManager[] { tm }, null);

SSLSocketFactory factory = context.getSocketFactory();



System.out

.println("Opening connection to " + host + ":" + port + "...");

SSLSocket socket = (SSLSocket) factory.createSocket(host, port);

socket.setSoTimeout(10000);

try {

System.out.println("Starting SSL handshake...");

socket.startHandshake();

socket.close();

System.out.println();

System.out.println("No errors, certificate is already trusted");

} catch (SSLException e) {

System.out.println();

e.printStackTrace(System.out);

}



X509Certificate[] chain = tm.chain;

if (chain == null) {

System.out.println("Could not obtain server certificate chain");

return;

}



BufferedReader reader = new BufferedReader(new InputStreamReader(

System.in));



System.out.println();

System.out.println("Server sent " + chain.length + " certificate(s):");

System.out.println();

MessageDigest sha1 = MessageDigest.getInstance("SHA1");

MessageDigest md5 = MessageDigest.getInstance("MD5");

for (int i = 0; i < chain.length; i++) {

X509Certificate cert = chain[i];

System.out.println(" " + (i + 1) + " Subject "

+ cert.getSubjectDN());

System.out.println(" Issuer " + cert.getIssuerDN());

sha1.update(cert.getEncoded());

System.out.println(" sha1 " + toHexString(sha1.digest()));

md5.update(cert.getEncoded());

System.out.println(" md5 " + toHexString(md5.digest()));

System.out.println();

}



System.out

.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");

String line = reader.readLine().trim();

int k;

try {

k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;

} catch (NumberFormatException e) {

System.out.println("KeyStore not changed");

return;

}



X509Certificate cert = chain[k];

String alias = host + "-" + (k + 1);

ks.setCertificateEntry(alias, cert);



OutputStream out = new FileOutputStream("jssecacerts");

ks.store(out, passphrase);

out.close();



System.out.println();

System.out.println(cert);

System.out.println();

System.out

.println("Added certificate to keystore 'jssecacerts' using alias '"

+ alias + "'");

}



private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();



private static String toHexString(byte[] bytes) {

StringBuilder sb = new StringBuilder(bytes.length * 3);

for (int b : bytes) {

b &= 0xff;

sb.append(HEXDIGITS[b >> 4]);

sb.append(HEXDIGITS[b & 15]);

sb.append(' ');

}

return sb.toString();

}



private static class SavingTrustManager implements X509TrustManager {



private final X509TrustManager tm;

private X509Certificate[] chain;



SavingTrustManager(X509TrustManager tm) {

 = tm;

}



public X509Certificate[] getAcceptedIssuers() {

throw new UnsupportedOperationException();

}



public void checkClientTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

throw new UnsupportedOperationException();

}



public void checkServerTrusted(X509Certificate[] chain, String authType)

throws CertificateException {

this.chain = chain;

tm.checkServerTrusted(chain, authType);

}

}



}

 2、javac InstallCert.java 编译java文件,生成.class文件;

3、然后执行:java InstallCert hostname,比如:
java InstallCert maven.aliyun.com

会看到如下信息:

java InstallCert   
Loading KeyStore /usr/java/jdk1.6.0_16/jre/lib/security/cacerts...  
Opening connection to :443...  
Starting SSL handshake...  
  
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)  
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1476)  
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)  
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)  
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:846)  
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)  
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)  
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)  
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)  
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)  
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)  
    at InstallCert.main(InstallCert.java:63)  
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)  
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)  
    at sun.security.validator.Validator.validate(Validator.java:203)  
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)  
    at InstallCert$SavingTrustManager.checkServerTrusted(InstallCert.java:158)  
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)  
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:839)  
    ... 7 more  
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)  
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)  
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)  
    ... 13 more  
  
Server sent 2 certificate(s):  
  
 1 Subject CN=, O=example.com, C=US  
   Issuer  CN=Certificate Shack, O=example.com, C=US  
   sha1    2e 7f 76 9b 52 91 09 2e 5d 8f 6b 61 39 2d 5e 06 e4 d8 e9 c7   
   md5     dd d1 a8 03 d7 6c 4b 11 a7 3d 74 28 89 d0 67 54   
  
 2 Subject CN=Certificate Shack, O=example.com, C=US  
   Issuer  CN=Certificate Shack, O=example.com, C=US  
   sha1    fb 58 a7 03 c4 4e 3b 0e e3 2c 40 2f 87 64 13 4d df e1 a1 a6   
   md5     72 a0 95 43 7e 41 88 18 ae 2f 6d 98 01 2c 89 68   
  
Enter certificate to add to trusted keystore or 'q' to quit: [1]

4、输入1,回车,然后会在当前的目录下产生一个名为“ssecacerts”的证书。该证书与InstallCert.java文件同级。

将证书拷贝到$JAVA_HOME/jre/lib/security目录下,或者通过以下方式:
System.setProperty("javax.Net.ssl.trustStore", "你的jssecacerts证书路径");

注意:因为是静态加载,所以要重新启动你的Web Server,证书才能生效。

如果还不能生效 参考如下:


1. 删除所有.lastUpdated结尾文件

2. 添加以下内容, 至红框位置

-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true

查看maven的配置 查看maven日志_java_02

查看maven的配置 查看maven日志_System_03