我正在为我的SSL客户端实现主机名验证程序。我知道HTTPS URL连接的默认主机名验证程序是静态的。我的问题是我不希望主机名验证是静态的,因为我的客户端中有多个线程同时访问此主机名验证器。
目前我的代码看起来像这样:
我有一个用于主机名验证的内部类,
public class CreateHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
try {
if (mInstance.getHost().equals(InetAddress.getByName(hostname)))
return true;
else if (hostname.equals(mInstance.getHost().getHostAddress()))
return true;
else if (hostname.equals(mInstance.getHost().getCanonicalHostName()))
return true;
else
return false;
} catch (UnknownHostException e) {
System.out.println("Unknown Host");
}
return false;
}
}
}
我在构建端点时调用此类,
address = mInstance.getSecureConnectionEndpoint();
try {
HttpsURLConnection Connection = (HttpsURLConnection) address.openConnection();
CreateHostnameVerifier hv = new CreateHostnameVerifier();
Connection.setDefaultHostnameVerifier(hv);
} catch (IOException e1) {
e1.printStackTrace();
}
因为我使用setDefaultHostnameVerifer
并尝试通过执行Connection.setDefaultHostnameVerifier
以非静态方式访问它,我收到如下警告:
The static method setDefaultHostnameVerifier(HostnameVerifier) from the type HttpsURLConnection should be accessed in a static way
但是这种方法非常好,但是如果我尝试以非静态的方式访问它:
Connection.setHostnameVerifier(hv);
它不起作用。
有人可以解释我两者之间的区别,即setHostnameVerifer
和setDefaultHostnameVerifier
。
答案 0 :(得分:2)
我的问题是我不希望主机名验证是静态的,因为我的客户端中有多个线程同时访问此主机名验证器。
这个“要求”是基于误解。
使用相同HostnameVerifier
的多个线程没有本身错误。除非你做一些非常奇怪的事情,否则其中一个对象应该没有可变状态。如果您的共享对象HostnameVerifier
实例是安全发布的(并且是不可变的),则可以安全地使用多个线程而无需同步。
有人可以向我解释两者之间的区别,即
setHostnameVerifier
和setDefaultHostnameVerifier
。
HttpsURLConnection.setHostnameVerifier
的javadoc解释了它:
public void setHostnameVerifier(HostnameVerifier v)
为此实例设置
HostnameVerifier
。此类的新实例继承由setDefaultHostnameVerifier
设置的默认静态主机名验证程序。调用此方法会替换此对象的HostnameVerifier
。
setHostnameVerifier
不适合你的一个可能原因可能是你称之为太晚了;即在建立连接之后,已经进行了验证。
避免警告的方法是设置默认验证程序,如下所示:
HttpsURLConnection.setDefaultHostnameVerifier(hv);
这是一个静态方法,因此应该通过类名而不是通过实例引用来调用。 (这就是警告告诉你的......)