🛡️ HTTPS
为保证网络访问安全,现在大多数企业都会选择使用SSL验证来提高网站的安全性。
所以Forest自然也加入了对HTTPS的处理,现在支持单向认证和双向认证的HTTPS请求。
# 单向认证
如果访问的目标站点的SSL证书由信任的Root CA发布的,那么您无需做任何事情便可以自动信任
public interface Gitee {
@Request(url = "https://gitee.com")
String index();
}
2
3
4
5
Forest的单向验证的默认协议为TLS
,如果一些站点的API不支持该协议,您可以在全局配置中将ssl-protocol
属性修改为其它协议,如:SSL
, TLS
, TLSv1.1
, TLSv1.2
,TLSv1.3
, SSLv3
等等。
forest:
...
ssl-protocol: TLS
2
3
全局配置可以配置一个全局统一的SSL协议,但现实情况是有很多不同服务(尤其是第三方)的API会使用不同的SSL协议,这种情况需要针对不同的接口设置不同的SSL协议。
/**
* 在某个请求接口上通过 sslProtocol 属性设置单向SSL协议
*/
@Get(
url = "https://localhost:5555/hello/user",
sslProtocol = "TLS"
)
ForestResponse<String> truestSSLGet();
2
3
4
5
6
7
8
在一个个方法上设置太麻烦,也可以在 @BaseRequest
注解中设置一整个接口类的SSL协议
@BaseRequest(sslProtocol = "TLS")
public interface SSLClient {
@Get("https://localhost:5555/hello/user")
String testSend();
}
2
3
4
5
6
7
# 简单双向认证
若是需要在Forest中进行双向验证的HTTPS请求,也很简单。
在全局配置中添加keystore
配置:
forest:
...
ssl-key-stores:
- id: keystore1 # id为该keystore的名称,必填
file: test.keystore # 公钥文件地址
keystore-pass: 123456 # keystore秘钥
cert-pass: 123456 # cert秘钥
protocols: TLS # SSL协议
2
3
4
5
6
7
8
<forest:configuration>
<forest:ssl-keystore
id="keystore1"
file="test.keystore"
keystorePass="123456"
certPass="123456"
protocols="TLS"/>
</forest:configuration>
2
3
4
5
6
7
8
// 获取Forest全局配置对象
configuration = Forest.config();
// 实例化 SSLKeyStore 对象,并输入参数
SSLKeyStore sslKeyStore = new SSLKeyStore(
"keystore1",
"ssl_client.keystore",
"client",
"456789",
null,
null);
// 注册 SSLKeyStore 对象
configuration.registerKeyStore(sslKeyStore);
2
3
4
5
6
7
8
9
10
11
12
// Make sure to add code blocks to your code group
接着,在@Request
中引入该keystore
的id
即可
@Get(url = "/user_info", keyStore = "keystore1")
ForestResponse<String> getUserInfo();
2
另外,您也可以在全局配置中配多个keystore
:
forest:
...
ssl-key-stores:
- id: keystore1 # 第一个keystore
file: test1.keystore
keystore-pass: 123456
cert-pass: 123456
protocols: SSL
- id: keystore2 # 第二个keystore
file: test2.keystore
keystore-pass: abcdef
cert-pass: abcdef
protocols: TLS
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
随后在某个具体@Request
中配置其中任意一个keystore
的id
都可以
# 更复杂的SSL验证
对于一些更复杂的SSL验证,光靠简单的配置无法完全应付,但在Forest中也可以通过自定义SSLSocketFactory
和HostnameVerifier
的方式提供更灵活的解决方案
# 自定义SSLSocketFactory
Forest提供了SSLSocketFactoryBuilder
接口,通过实现该接口可以自定义SSLSocketFactory
/**
* 自定义 SSLSocketFactory 构造器
*/
public class MySSLSocketFactoryBuilder implements SSLSocketFactoryBuilder {
/**
* 获取SSL Socket Factory
*/
@Override
public SSLSocketFactory getSSLSocketFactory(ForestRequest request, String protocol) throws Exception {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,
new TrustManager[] { new TrustAllManager() },
new SecureRandom());
return sslContext.getSocketFactory();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
然后通过@SSLSocketFactoryBuilder
注解引入自定义的SSLSocketFactoryBuilder
接口实现类
@Get("/user_info")
@SSLSocketFactoryBuilder(MySSLSocketFactoryBuilder.class)
ForestRequest<String> getUserInfo();
2
3
# 自定义HostnameVerifier
在Forest中,也可以指定自定义的HostnameVerifier
接口实现类
/**
* 自定义主机名验证器
*/
public class MyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
System.out.println("do MyHostnameVerifier");
if ("localhost".equals(s)) {
return false;
}
return true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
然后通过@SSLHostnameVerifier
注解引入自定义的主机名验证器类
@Get("/user_info")
@SSLHostnameVerifier(MyHostnameVerifier.class)
ForestRequest<String> getUserInfo();
2
3