Okhttp hostnameVerifier详解

Okhttp hostnameVerifier详解 hostnameVerifier 方法简介核心原理参考资料 方法简介
本篇博文以Okhttp 4.6.0来解析hostnameVerfier的作用,顾名思义,

hostnameVerifier

方法概述基本原理参考资料

方法简介

在这篇博文中,我们将使用Okhttp 4.6.0 来分析hostnameVerfier 的作用。顾名思义,该方法的主要功能是识别主机名的合法性。 Okhttp初始化后,您可以自己设置hostnameVerfier。

新的OkHttpClient.Builder()

.connectTimeout(20, TimeUnit.SECONDS)

.readTimeout(20, TimeUnit.SECONDS)

.writeTimeout(35, TimeUnit.SECONDS)

.hostnameVerifier(new HostnameVerifier() {

@覆盖

公共布尔验证(字符串主机名,SSLSession会话){

//注意,生产中不应该直接写true。

返回真。

}

})

。建造();

不过网上有很多资料是把verfiy直接变回true,这是非常危险的。当然,如果verify返回fasle,则说明主机名验证失败,http请求不会成功。例如,当您使用博客地址发起http 请求时,您会收到类似于以下内容的错误消息:

{http errorCode=-500, mErrorMsg=主机名yanchen.blog.csdn.net未验证:

证书: sha256/tlnf6pbfeu257hnJ9e6j4A1ZWH3vVMzn3Zn3F9kLHdg=

DN: CN=*.blog.csdn.net

subjectAltNames: [*.blog.csdn.net]}

执行后在RealConnection内执行Verify。

除了自定义的hostnameVerfier之外,Okhttp还提供了默认的实现。接下来我们来分析一下内部原理。

核心原理

OkHostnameVerifier 内置于Okhttp 中,该方法通过session.peerCertificates[0] 获取X509Certificate 形式的证书对象。

覆盖fun verify(host: String, session: SSLSession): Boolean {

请返回并尝试{

验证(主机,session.peerCertificates [0]作为X509Certificate)

捕获(_: SSLException){

错误

}

}

有趣的验证(主机:字符串,证书: X509Certificate):布尔值{

返回如果{

host.canParseAsIpAddress() – verifyIpAddress(主机,证书)

else – verifyHostname(主机,证书)

}

}

X509Certificate 对象提供一组get 方法,用于检索一组信息,例如证书的公钥和序列号。请参考以下内容:

最后,调用verifyHostname 方法,在获取SubjectAltName 后,将主机名与SubjectAltName 进行比较,如果匹配则返回true,如果不匹配则返回fasle。

私人乐趣verifyHostname(主机名:字符串,证书: X509Certificate):布尔值{

val 主机名=主机名.toLowerCase(Locale.US)

返回getSubjectAltNames(证书, ALT_DNS_NAME).any {

验证主机名(主机名,它)

}

}

//比较主机名和SubjectAltName

private fun verifyHostname(hostname: String?pattern: String?): Boolean {

var 主机名=主机名

var 模式=模式

//检查客户端域名的有效性

if (主机名.isNullOrEmpty() ||

主机名.startsWith(\’.\’) ||

主机名.endsWith(\’.\’)) {

//无效域名

返回错误

}

//检查证书中SubjectAltName的有效性

if (pattern.isNullOrEmpty() ||

模式.startsWith(\’.\’) ||

模式.endsWith(\’.\’)) {

//无效模式/域名

返回错误

}

//如果主机名和模式不是绝对域名,则将其转换为绝对域名并规范化。

//但是,这是必要的,因为服务器证书不包含绝对值。

//名称或模式,但也必须被视为任意主机名。

//出于整理目的,提供给此方法的任何内容都必须被视为绝对值

//到服务器证书。

//www.android.com 匹配www.android.com

//www.android.com 匹配www.android.com。

//www.android.com 匹配www.android.com。

//www.android.com 匹配www.android.com

if (!hostname.endsWith(\’.\’)) {

主机名+=\’.\’

}

if (!pattern.endsWith(\’.\’)) {

模式+=\’.\’

}

//主机名和模式现在是绝对域名。

模式=pattern.toLowerCase(Locale.US)

//主机名和模式现在为小写——域名不区分大小写。

if (\’*\’ !内部模式) {

//不是通配符模式——主机名和模式必须完全匹配。

主机名==返回模式

}

//通配符模式

//通配符模式规则:

//1. 星号(*)只允许出现在最左边的域名标签中,

//仅该标签内的字符(即,它必须匹配整个最左边的标签)。

//例如,允许使用*.example.com,但是*a.example.com、a*.example.com、

//不允许a*b.example.com、a.*.example.com。

//2. 域名标签之间不能匹配星号(*)。

//例如,*.example.com 匹配test.example.com,但不匹配

//sub.test.example.com。

//3. 单标签域名不允许使用通配符模式。

if (!pattern.startsWith(\’*.\’) || pattern.indexOf(\’*\’, 1) !=-1) {

//星号(*)只能出现在最左边的域名标签中,并且必须是唯一的

//该标签中的字符

返回错误

}

//Optimization: 检查主机名是否太短而无法匹配模式。

//星号必须匹配整个最左边的标签,因此它必须与模式长度相同。

//主机名以非空标签开头。因此,星号必须匹配一个或多个字符。

if (主机名.lengthpattern.length) {

return false //主机名太短,无法匹配模式。

}

if (\’*.\’==模式) {

return false //单标签域名通配符模式——不允许。

}

//主机名必须以星号后面的模式中的字段结尾。

val 后缀=pattern.substring(1)

if (!hostname.endsWith(suffix)) {

return false //主机名不以后缀结尾。

}

//确保域名标签之间的星号不匹配。

val suffixStartIndexInHostname=主机名.length – 后缀.length

if (suffixStartIndexInHostname 0

主机名.lastIndexOf(\’.\’, suffixStartIndexInHostname – 1) !=-1) {

return false //域名标签之间的星号匹配——不允许。

}

//主机名与模式匹配。

返回真

}

那么SubjectAltName是什么?您可以通过以下方式获取它。

新的主机名验证器(){

@覆盖

公共布尔验证(字符串主机名,SSLSession会话){

尝试{

X509Certificate x509Certificate=(X509Certificate) session.getPeerCertificates()[0];

集合列表?

for (列表? subjectAltName : subjectAltNames) {

if (subjectAltName==null || subjectAltName.size() 2) 继续;

int 类型=(int)subjectAltName.get(0);

if (type!=2) 继续;

字符串altName=(String)subjectAltName.get(1);

LogUtil.logD(\’hostnameVerifier\’,\’x509Certificate altName==\’+altName);

}

} catch (异常e) {

}

返回真。

}

}

Okhttp内置的主机名验证逻辑非常简单,您可以自己检查源代码。

参考资料

Android CertificateSource 获取和获取系统根证书Android https TrustManager checkServerTrusted Android RootTrustManager 详解证书验证简单分析Android CertificateSource 获取和获取系统根证书Android NSSP 简单解释Okhttp 简单分析RealConnection 建立的链接

以上相关内容来源网络对#Okhttp hostnameVerifier的详细描述,仅供参考。相关信息请参见官方公告。

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93037.html

(0)
CSDN's avatarCSDN
上一篇 2024年7月5日 上午6:12
下一篇 2024年7月5日 上午6:12

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注