Java 不带值的可选toString已断开
我有一个基于证书的身份验证:Java 不带值的可选toString已断开,java,spring,optional,Java,Spring,Optional,我有一个基于证书的身份验证: import java.security.cert.X509Certificate; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; import javax.inject.Named; import javax.naming.InvalidNameException; im
import java.security.cert.X509Certificate;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
@Named
public class UsernameService {
private static final String MISSING_NAME = null;
private static final Logger LOG = Logger.getLogger(UsernameService.class.getCanonicalName());
@Inject
private final Optional<X509Certificate> cert = null;
public String currentRequestUsername() {
if (cert.isPresent()) {
try {
LOG.finest("Check Certificate: " + cert); // <- exception!
for (Rdn rdn : new LdapName(cert.get().getSubjectDN().getName()).getRdns()) {
LOG.finest("Check RDN entry for Common name(cn): " + rdn);
if (rdn.getType().equals("CN")) {
LOG.finer("Found Username: " + rdn.getValue().toString());
return rdn.getValue().toString();
}
}
} catch (InvalidNameException e) {
LOG.log(Level.CONFIG, "Parse DName impossible: " + cert.get().getSubjectDN().getName() + ".", e);
} catch (NullPointerException e) {
LOG.log(Level.FINE, e.getMessage(), e);
}
}
return MISSING_NAME;
}
}
但我在控制台中遇到一个异常:
org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public abstract java.lang.String java.security.cert.Certificate.toString()] on target [null]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at $java.security.cert.X509Certificate$$EnhancerBySpringCGLIB$$96797f0e.toString(<generated>)
at java.util.Formatter$FormatSpecifier.printString(Formatter.java:2886)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2763)
at java.util.Formatter.format(Formatter.java:2520)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at java.util.Optional.toString(Optional.java:346)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at XXX.UsernameService.currentRequestUsername(UsernameService.java:27)
...
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
org.springframework.aop.aop异常:aop配置似乎无效:尝试在目标[null]上调用方法[public abstract java.lang.String java.security.cert.Certificate.toString()];嵌套异常为java.lang.IllegalArgumentException:对象不是声明类的实例
位于org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
位于org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
位于org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
在org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:163)上
位于org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
位于org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
位于org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:186)
位于org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
位于$java.security.cert.X509Certificate$$EnhancerBySpringCGLIB$$96797f0e.toString()
位于java.util.Formatter$FormatSpecifier.printString(Formatter.java:2886)
位于java.util.Formatter$FormatSpecifier.print(Formatter.java:2763)
位于java.util.Formatter.format(Formatter.java:2520)
位于java.util.Formatter.format(Formatter.java:2455)
位于java.lang.String.format(String.java:2940)
位于java.util.Optional.toString(Optional.java:346)
位于java.lang.String.valueOf(String.java:2994)
在java.lang.StringBuilder.append(StringBuilder.java:131)
位于XXX.UsernameService.currentRequestUsername(UsernameService.java:27)
...
原因:java.lang.IllegalArgumentException:对象不是声明类的实例
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中
有什么想法吗?现在我在
IllegalArgumentException
的构造函数中创建了一个断点。
然后我后退两步,检查CDI调用
我看到一个NullBean
有一个org.springframework.beans.factory.support.NullBean
的实例
因此可选项似乎不是null
,但bean是一个null bean
我的解决方案是简单地捕获一个异常,即NullBean不是证书
import java.security.cert.X509Certificate;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
@Named
public class UsernameService {
private static final String MISSING_NAME = null;
private static final Logger LOG = Logger.getLogger(UsernameService.class.getCanonicalName());
@Inject
private final Optional<X509Certificate> cert = null;
public String currentRequestUsername() {
if (cert.isPresent()) {
try {
LOG.finest("Check Certificate: " + cert);
for (Rdn rdn : new LdapName(cert.get().getSubjectDN().getName()).getRdns()) {
LOG.finest("Check RDN entry for Common name(cn): " + rdn);
if (rdn.getType().equals("CN")) {
LOG.finer("Found Username: " + rdn.getValue().toString());
return rdn.getValue().toString();
}
}
} catch (InvalidNameException e) {
LOG.log(Level.CONFIG, "Parse DName impossible: " + cert.get().getSubjectDN().getName() + ".", e);
} catch (NullPointerException e) {
LOG.log(Level.FINE, e.getMessage(), e);
} catch (RuntimeException e) {
LOG.log(Level.FINE, e.getMessage(), e);
}
}
return MISSING_NAME;
}
}
导入java.security.cert.x509证书;
导入java.util.Optional;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.inject.inject;
导入javax.inject.Named;
导入javax.naming.InvalidNameException;
导入javax.naming.ldap.LdapName;
导入javax.naming.ldap.Rdn;
@命名
公共类UsernameService{
私有静态最终字符串缺少\u NAME=null;
私有静态最终记录器LOG=Logger.getLogger(UsernameService.class.getCanonicalName());
@注入
私有最终可选证书=null;
公共字符串currentRequestUsername(){
如果(证书isPresent()){
试一试{
LOG.finest(“检查证书:+cert”);
对于(Rdn Rdn:新的LdapName(证书get().getSubjectDN().getName()).getRdns()){
LOG.finest(“检查公共名称(cn)的RDN条目:”+RDN);
if(rdn.getType().equals(“CN”)){
LOG.finer(“找到的用户名:+rdn.getValue().toString());
返回rdn.getValue().toString();
}
}
}捕获(InvalidNameException e){
LOG.LOG(Level.CONFIG,“不可能解析DName:”+cert.get().getSubjectDN().getName()+”,e);
}捕获(NullPointerException e){
LOG.LOG(Level.FINE,e.getMessage(),e);
}捕获(运行时异常e){
LOG.LOG(Level.FINE,e.getMessage(),e);
}
}
返回缺少的_名称;
}
}
可选证书=null
wrong@Lino为什么?5个字符—更多要写—不要对字段使用可选。使用它作为返回值,这就是它的用途。决不允许可选的为空。您创建的问题正是Optional
应该帮助您解决的问题。您的Optional
显然持有(非空)证书。猜测可能是证书对象以某种方式无效。可能它不应该包含空值?如何将X509Certificate
bean注入可选证书
?另外,它被声明为final并初始化为null?
import java.security.cert.X509Certificate;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
@Named
public class UsernameService {
private static final String MISSING_NAME = null;
private static final Logger LOG = Logger.getLogger(UsernameService.class.getCanonicalName());
@Inject
private final Optional<X509Certificate> cert = null;
public String currentRequestUsername() {
if (cert.isPresent()) {
try {
LOG.finest("Check Certificate: " + cert);
for (Rdn rdn : new LdapName(cert.get().getSubjectDN().getName()).getRdns()) {
LOG.finest("Check RDN entry for Common name(cn): " + rdn);
if (rdn.getType().equals("CN")) {
LOG.finer("Found Username: " + rdn.getValue().toString());
return rdn.getValue().toString();
}
}
} catch (InvalidNameException e) {
LOG.log(Level.CONFIG, "Parse DName impossible: " + cert.get().getSubjectDN().getName() + ".", e);
} catch (NullPointerException e) {
LOG.log(Level.FINE, e.getMessage(), e);
} catch (RuntimeException e) {
LOG.log(Level.FINE, e.getMessage(), e);
}
}
return MISSING_NAME;
}
}