I am trying to parse the html of the following URL:
https://www.smuc.ac.kr/mbs/smuc/jsp/board/list.jsp?boardId=6993&id=smuc_040100000000
I'm getting the following error:
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:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 15 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 21 more
This is my code:
public class MainActivity extends AppCompatActivity {
private ListView listView;
private TextView textView;
public ArrayList<String> arrayList = new ArrayList<String>();
private ArrayAdapter<String> arrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
new Insert().execute();
arrayAdapter = new ArrayAdapter<String>(MainActivity.this, R.layout.list_ok, R.id.text, arrayList );
}
class Insert extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
try {
// Connection.Response res = Jsoup.connect("https://www.smuc.ac.kr/mbs/smuc/index.jsp")
// .method(Connection.Method.POST)
// .execute();
Document document = Jsoup.connect("https://www.smuc.ac.kr/mbs/smuc/jsp/board/list.jsp?boardId=6993&id=smuc_040100000000").get();
Elements elements = document.select(".tit");
arrayList.clear();
for (Element element : elements) {
arrayList.add(element.text());
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result){
listView.setAdapter(arrayAdapter);
}
}
}
This issue might arise if you are using a self-signed certificate or a certificate that's been issued by an internal certificate authority, or if your clients (e.g., browser, Java) are outdated. Trust is handled by having the root and intermediate certificates of your SSL certificate on a trusted keystore.
Take the particular URL from the error and copy it to a browser (In the above error the url is https://repository.mulesoft.org/releases/). Now to the left of the URL there is a lock icon ( ). Click on this icon and a window will pop up. From the window, select the certificate.
This problem is therefore caused by a certificate that is self-signed (a CA did not sign it) or a certificate chain that does not exist within the Java truststore. Java does not trust the certificate and fails to connect to the application.
PKIX stands for Public Key Infrastructure X509. Whenever Java attempts to connect to another application over SSL, the connection will only succeed if it can trust the application. In Java, trust is handled with a keystore, also known as the truststore (typically <agent_home>/<version_number>/conf/cacerts.
The selected answer will not work with latest releases of JSoup as validateTLSCertificates is deprecated and removed. I have created the following helper class :
public class SSLHelper {
static public Connection getConnection(String url){
return Jsoup.connect(url).sslSocketFactory(SSLHelper.socketFactory());
}
static private SSLSocketFactory socketFactory() {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory result = sslContext.getSocketFactory();
return result;
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException("Failed to create a SSL socket factory", e);
}
}
}
Then I simply call it as follows:
Document doc = SSLHelper.getConnection(url).userAgent(USER_AGENT).get();
(*) - https://dzone.com/articles/how-setup-custom - helpful in coming up with the solution
Note: JSoup has deprecated and removed the validateTLSCertificates
method in version 1.12.1. See this answer for an alternative solution.
Prior to JSoup version 1.12.1, ignore TLS validation as follows:
Document doc = Jsoup.connect("URL").timeout(10000).validateTLSCertificates(false).get();
Since reading the page also takes a while, increase the timeout timeout(10000)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With