我有一台gRPC服务器,该服务器正在使用相互TLS进行加密和身份验证。因此,每个连接到该服务器的客户端都提供一个SSL证书,我想从公共密钥大小小于2048位的客户端中<。似乎还没有直接的方法可以做到这一点。
我可以通过ServerInterceptor
这样操作public class SSLInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
try {
SSLSession sslSession = call.getAttributes().get(Grpc.TRANSPORT_ATTR_SSL_SESSION);
RSAPublicKeyImpl pk = (RSAPublicKeyImpl) sslSession.getPeerCertificates()[0].getPublicKey();
if (pk.getModulus().bitLength() < 2048) {
// reject call
}
// proceed with the call
} catch (SSLPeerUnverifiedException e) {
// do something
}
...
}
}
这是一种不好的方法,因为已经在连接之后进行验证建立的。
- 仅在发出请求/调用时才触发验证。
- 每个呼叫都涉及额外的验证开销。
- 如果验证失败,则仅拒绝呼叫,而不拒绝与客户端的连接。
javax.net.ssl.TrustManagerFactory
提供自己的SslContextBuilder
来自定义证书检查。您可能想要实现X509ExtendedTrustManager
,进行检查,然后委派给“真实”实现,以进行其余的证书链检查。您可以执行类似的操作以获取默认配置TrustManagerFactory
:
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
// loop through tmf.getTrustManagers() checking for one implementing X509TrustManager