扩展java.security.cert.X509Certificate的正确方法是什么?

时间:2017-10-26 19:22:08

标签: java x509certificate

扩展Java X509Certificate以便为其添加自定义函数的正确方法是什么?让我们来看看:

public abstract class MyX509Certificate extends java.security.cert.X509Certificate {
    protected X509Certificate() {
        super();
    }
}

通常,您只需从密钥库获取证书并将其转换为:

X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);

我试图像这样投我的:

MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);

但我明白了:

  

线程中的异常" main" java.lang.ClassCastException:sun.security.x509.X509CertImpl无法强制转换为ca.carillon.crypto.cert.MyX509Certificate

为什么?

2 个答案:

答案 0 :(得分:2)

错误消息显示:

  

java.lang.ClassCastException:sun.security.x509.X509CertImpl无法强制转换为ca.carillon.crypto.cert.MyX509Certificate

它基本上说一种类型(sun.security.x509.X509CertImpl)无法转换为其他类型(您的MyX509Certificate类)。

sun.security.x509.X509CertImplsubclass of java.security.cert.X509Certificate,并且keystore.getCertificate方法返回了它。

X509Certificateabstract classkeystore.getCertificate将返回它的内部实现(子类)。这个子类可能会有所不同,具体取决于您的环境(JVM,提供程序等)。在这种情况下,它会返回sun.security.x509.X509CertImpl - 您无法在任何地方看到此课程,因为它是JVM内部的,并且在大多数情况下您实际上并不需要知道它。您需要知道的只是X509Certificate

当您创建自己的X509Certificate子类时,层次结构将如下所示:

                   X509Certificate <- super class
                           |
         ------------------------------------- 
         |                                   |
sun.security.x509.X509CertImpl        MyX509Certificate  <- subclasses of X509Certificate

kesytore(X509CertImpl)和您的自定义类(MyX509Certificate)返回的类都是X509Certificate的子类。

当密钥库返回X509CertImpl时,可以将其强制转换为X509Certificate(子类实例可以分配给具有超类类型的变量)。

但如果你试图这样做:

MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);

密钥库返回X509CertImplX509Certificate,但 <{1}} - 你不能扮演一个兄弟姐妹&#34;上课到另一个。 MyX509Certificate只知道其超类(X509CertImpl),但它不了解X509Certificate

如果您想为MyX509Certificate添加功能,或许扩展它不是最佳解决方案,您应该选择"Composition over Inheritance" approach

您可以创建一个具有一个X509Certificate(AKA&#34;包装器&#34;)的类,并使用它添加功能:

X509Certificate

然后使用密钥库返回的证书创建此类:

public class MyCustomCertificate {

    // wraps a X509Certificate
    private X509Certificate cert;

    public MyCustomCertificate(X509Certificate cert) {
        this.cert = cert;
    }

    public void myCustomFunctionality1() {
        // do something with this.cert
    }

    public void myCustomFunctionality2() {
        // do something with this.cert
    }

    // and so on...
}

X509Certificate x509Cert = (X509Certificate) keystore.getCertificate(alias); MyCustomCertificate myCert = new MyCustomCertificate(x509Cert); 有许多未实现的方法,扩展它将需要你实现它们(这不值得做,IMO)。相反,您可以使用密钥库返回的证书(已经实现了所有这些方法)并添加了您想要的功能。

但是,如果您真的想扩展X509Certificate,可以将方法委托给包装证书:

X509Certificate

答案 1 :(得分:1)

如其他答案中所述,您不应该尝试创建自己的类。您应该使用另一个安全提供程序。

要回答您关于 为什么 的实际问题,您无法向自己的班级投票。实例化的对象不是MyX509Certificate,因此无法强制转换。如果类是该类型,则只能转换为类型。

例如:

public abstract class AbstractParentClass {
}

public class ChildClassA extends AbstractParentClass {
}

public class ChildClassB extends AbstractParentClass {
}

您现在可以实例化ChildClassA并将其分配给AbstractParentClass类型的变量,然后将其转换为ChildClassA变量

public static void main(String[] args){
    AbstractParentClass instance = new ChildClassA();
    ChildClassA sameInstance = (ChildClassA) instance;
}

无法 做的是将其强制转换为不属于其类分类的类。

AbstractParentClass instance = new ChildClassA();
// This is runtime error because ChildClassB is not a ChildClassA
ChildClassB sameInstance = (ChildClassB) instance;

因此,除非您自己实例化该类,而不是因为您正在从密钥库中检索它,否则该类不是MyX509Certificate类型。