如何解决javax.net.ssl.SSLPeerUnverifiedException异常:主机名.com未经验证

23

我遇到了以下错误:Hostname domain.com not verified:而不是"javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated"。我之前可以连接到不同的主机,但在这个主机上我遇到了问题,该如何解决?

 javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified:
    certificate: sha1//WQM9QbrKs6DCFa9qN/EIw1ywBw=
    DN: CN=*.ipage.com,OU=Domain Control Validated - RapidSSL(R),OU=See www.rapidssl.com/resources/cps (c)14,OU=GT29505539
    subjectAltNames: [*.ipage.com, ipage.com]
            at com.squareup.okhttp.Connection.connectTls(Connection.java:244)
            at com.squareup.okhttp.Connection.connectSocket(Connection.java:199)
            at com.squareup.okhttp.Connection.connect(Connection.java:172)
            at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:367)
            at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
            at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:328)
            at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
            at com.squareup.okhttp.Call.getResponse(Call.java:267)

这是我的代码

  try {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.accumulate("name", name);
                    jsonObject.accumulate("password", pass);
                    jsonObject.accumulate("email", emails);
                    json = jsonObject.toString();
                    Log.e("MYAPP", "getjson");

                } catch (JSONException e) {
                    Log.e("MYAPP", "unexpected JSON exception", e);
                }
                try{
                    RequestBody formBody = new FormEncodingBuilder()
                            .add("name", name)
                            .build();
                    Request request = new Request.Builder()
                            .url("https://justedhak.com/Files/users.php")
                            .post(formBody)
                            .build();

1
@Moudiz 用http实现吧,也许服务器端没有https可用。 - denis_lor
2
@Moudiz 是的,你需要联系主机。 - rusted brain
1
让它保持不变,我太懒了,不想再写一遍答案 :P 很高兴能对你有所帮助 :) - rusted brain
1
请查看我在以下链接中的回答:https://dev59.com/mo_ea4cB1Zd3GeqPVfuh#33071430 - BNK
1
非常感谢您在我的所有问题上的帮助,我的问题是我没有从主机购买证书。因此,我通过http访问php文件,将来可能会使用SSL @BNK。 - Moudiz
显示剩余19条评论
3个回答

32

更新

由于异常为javax.net.ssl.SSLPeerUnverifiedException: 主机名 justedhak.com 未经验证,并且使用了DN: CN=*.ipage.com...subjectAltNames: [*.ipage.com, ipage.com]

因此,您可以按照以下方式替换我的示例代码中的setHostnameVerifier(因为不建议使用return true):

client.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                //return true;
                HostnameVerifier hv =
                        HttpsURLConnection.getDefaultHostnameVerifier();
                return hv.verify("ipage.com", session);
            }
        });

您将会得到如下屏幕截图所示的成功结果。


如果您想只在学习或开发环境中使用该主机的HTTPS,您可以参考以下步骤,当然您也可以将我的GET请求改为您的POST请求:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.textView);
        mHandler = new Handler(Looper.getMainLooper());
        OkHttpClient client = new OkHttpClient();
        client.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        Request request = new Request.Builder()
                .url("https://justedhak.com/Files/users.php")
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                // do something...
                Log.e(LOG_TAG, e.toString());
            }

            @Override
            public void onResponse(Response response) throws IOException {
                // do something...
                Log.i(LOG_TAG, response.body().string());
            }
        });
    }

这是屏幕截图:

BNK's screenshot

您也可以在以下问题中阅读更多内容:

如何信任证书


在我看来,您可以在此处阅读:http://developer.android.com/training/articles/security-ssl.html,位于“主机名验证的常见问题”部分。 - BNK
我的意思是仅针对“return true”,对于return hv.verify("...com", session);我不太确定,尽管您可以在Google的文档中找到“caution”。 - BNK
好的,我会阅读一下。顺便问一下,你有关于用户登录/注销会话的答案吗? - Moudiz
如果这是你要问的问题,请查看http://stackoverflow.com/questions/31466653/how-to-use-security-authentication-authorization-in-asp-web-api/31471027#31471027 :) - BNK
2
@i-Droid 我认为它可以工作,你可以尝试使用以下代码: OkHttpClient client = new OkHttpClient.Builder() .hostnameVerifier(new ...) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL_BASE) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); - BNK
显示剩余2条评论

2
我通过添加主机名验证器并将其返回为true来解决了retrofit2中的问题。
OkHttpClient client = new OkHttpClient.Builder()
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                            return true;
                        }
                    })
                    .connectTimeout(100, TimeUnit.SECONDS)
                    .readTimeout(100, TimeUnit.SECONDS).build();

1
我在Jenkins访问GIT时遇到了相同的错误,实际上是因为GIT地址定期更改(基于AWS),而Jenkins具有GIT地址,该地址不再有效。重启jvm就足以解决问题,但减少ttl将是最好的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接