扩展 java.security.cert.X509Certificate 的正确方法是什么?
What is the proper way to extend java.security.cert.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);
但我得到:
Exception in thread "main" java.lang.ClassCastException: sun.security.x509.X509CertImpl cannot be cast to ca.carillon.crypto.cert.MyX509Certificate
为什么?
如其他答案中所述,您不应尝试创建自己的 class。您应该使用另一个安全提供程序。
要回答您关于 为什么 的实际问题,您不能投射到 class 是有原因的。实例化对象不是 MyX509Certificate
,因此无法转换。 class 只能转换为该类型。
例如:
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;
}
你不能做的是将它转换为不属于其class的class分类法。
AbstractParentClass instance = new ChildClassA();
// This is runtime error because ChildClassB is not a ChildClassA
ChildClassB sameInstance = (ChildClassB) instance;
因此,除非您自己实例化 class,否则您不是因为您是从密钥库中检索它,否则 class 不是 MyX509Certificate
类型.
错误消息说:
java.lang.ClassCastException: sun.security.x509.X509CertImpl cannot be cast to ca.carillon.crypto.cert.MyX509Certificate
基本上是说一种类型 (sun.security.x509.X509CertImpl
) 不能转换为另一种类型 (你的 MyX509Certificate
class)。
sun.security.x509.X509CertImpl
是一个 subclass of java.security.cert.X509Certificate
并且正在 return 由 keystore.getCertificate
方法编辑。
发生的事情是 X509Certificate
是一个 abstract class,而 keystore.getCertificate
将 return 是它的一个内部实现(一个子class)。并且这个 subclass 可以不同,这取决于您的环境(JVM、提供程序等)。在这种情况下,它是 returning a sun.security.x509.X509CertImpl
- 你不会在任何地方看到这个 class 因为它在 JVM 内部,而且在大多数情况下你实际上不需要知道它.您只需要知道它是一个 X509Certificate
.
当您创建 X509Certificate
的自己的子 class 时,层次结构将如下所示:
X509Certificate <- super class
|
-------------------------------------
| |
sun.security.x509.X509CertImpl MyX509Certificate <- subclasses of X509Certificate
由 kesytore (X509CertImpl
) 编辑的 class return 和您的自定义 class (MyX509Certificate
) 都是子class X509Certificate
.
的 es
当密钥库 return 是 X509CertImpl
时,可以将其转换为 X509Certificate
(subclass 实例可以分配给带有 super 的变量class 的类型)。
但是如果你尝试这样做:
MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);
密钥库正在 returning X509CertImpl
,这是 X509Certificate
,但 不是 MyX509Certificate
-您不能将 "sibling" class 转换为另一个。 X509CertImpl
只知道它的超级 class (X509Certificate
),但不知道 MyX509Certificate
.
如果您想向 X509Certificate
添加功能,也许扩展它不是最好的解决方案,您应该选择 "Composition over Inheritance" approach.
您可以创建一个 具有 一个 X509Certificate
(又称 "a wrapper")的 class 并使用它添加功能:
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...
}
然后您使用由密钥库 return 编辑的证书创建此 class:
X509Certificate x509Cert = (X509Certificate) keystore.getCertificate(alias);
MyCustomCertificate myCert = new MyCustomCertificate(x509Cert);
X509Certificate
有很多未实现的方法,扩展它需要你实现它们(这是不值得做的,IMO)。相反,您可以使用由密钥库(已经实现所有这些方法)编辑的证书 return 并添加您想要的功能。
不过,如果你真的想扩展 X509Certificate
,你可以将方法委托给包装证书:
public class MyCustomCertificate extends X509Certificate {
// 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
}
// delegate all X509Certificate methods to the wrapped certificate
public PublicKey getPublicKey() {
return this.cert.getPublicKey();
}
public Principal getSubjectDN() {
return this.cert.getSubjectDN();
}
// and so on...
}
扩展 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);
但我得到:
Exception in thread "main" java.lang.ClassCastException: sun.security.x509.X509CertImpl cannot be cast to ca.carillon.crypto.cert.MyX509Certificate
为什么?
如其他答案中所述,您不应尝试创建自己的 class。您应该使用另一个安全提供程序。
要回答您关于 为什么 的实际问题,您不能投射到 class 是有原因的。实例化对象不是 MyX509Certificate
,因此无法转换。 class 只能转换为该类型。
例如:
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;
}
你不能做的是将它转换为不属于其class的class分类法。
AbstractParentClass instance = new ChildClassA();
// This is runtime error because ChildClassB is not a ChildClassA
ChildClassB sameInstance = (ChildClassB) instance;
因此,除非您自己实例化 class,否则您不是因为您是从密钥库中检索它,否则 class 不是 MyX509Certificate
类型.
错误消息说:
java.lang.ClassCastException: sun.security.x509.X509CertImpl cannot be cast to ca.carillon.crypto.cert.MyX509Certificate
基本上是说一种类型 (sun.security.x509.X509CertImpl
) 不能转换为另一种类型 (你的 MyX509Certificate
class)。
sun.security.x509.X509CertImpl
是一个 subclass of java.security.cert.X509Certificate
并且正在 return 由 keystore.getCertificate
方法编辑。
发生的事情是 X509Certificate
是一个 abstract class,而 keystore.getCertificate
将 return 是它的一个内部实现(一个子class)。并且这个 subclass 可以不同,这取决于您的环境(JVM、提供程序等)。在这种情况下,它是 returning a sun.security.x509.X509CertImpl
- 你不会在任何地方看到这个 class 因为它在 JVM 内部,而且在大多数情况下你实际上不需要知道它.您只需要知道它是一个 X509Certificate
.
当您创建 X509Certificate
的自己的子 class 时,层次结构将如下所示:
X509Certificate <- super class
|
-------------------------------------
| |
sun.security.x509.X509CertImpl MyX509Certificate <- subclasses of X509Certificate
由 kesytore (X509CertImpl
) 编辑的 class return 和您的自定义 class (MyX509Certificate
) 都是子class X509Certificate
.
当密钥库 return 是 X509CertImpl
时,可以将其转换为 X509Certificate
(subclass 实例可以分配给带有 super 的变量class 的类型)。
但是如果你尝试这样做:
MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);
密钥库正在 returning X509CertImpl
,这是 X509Certificate
,但 不是 MyX509Certificate
-您不能将 "sibling" class 转换为另一个。 X509CertImpl
只知道它的超级 class (X509Certificate
),但不知道 MyX509Certificate
.
如果您想向 X509Certificate
添加功能,也许扩展它不是最好的解决方案,您应该选择 "Composition over Inheritance" approach.
您可以创建一个 具有 一个 X509Certificate
(又称 "a wrapper")的 class 并使用它添加功能:
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...
}
然后您使用由密钥库 return 编辑的证书创建此 class:
X509Certificate x509Cert = (X509Certificate) keystore.getCertificate(alias);
MyCustomCertificate myCert = new MyCustomCertificate(x509Cert);
X509Certificate
有很多未实现的方法,扩展它需要你实现它们(这是不值得做的,IMO)。相反,您可以使用由密钥库(已经实现所有这些方法)编辑的证书 return 并添加您想要的功能。
不过,如果你真的想扩展 X509Certificate
,你可以将方法委托给包装证书:
public class MyCustomCertificate extends X509Certificate {
// 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
}
// delegate all X509Certificate methods to the wrapped certificate
public PublicKey getPublicKey() {
return this.cert.getPublicKey();
}
public Principal getSubjectDN() {
return this.cert.getSubjectDN();
}
// and so on...
}