ps请求失败:java.security.NoSuchProviderException: SunJSSE

当web项目在tomcat中启动时,可以正确得建立https链接,发起请求并获得响应。

但是把web项目放到手机上使用i-jetty启动时,发起https请求失败。

 

检查后发现在建立SSLContext时报错:java.security.NoSuchProviderException: SunJSSE

 

建立SSLContext的代码为:

 

Java代码   收藏代码
  1. SSLContext sslContext = SSLContext.getInstance("SSL",”SunJSSE”);  

 

 

查看JDK API:


getInstance

public static SSLContext getInstance(String protocol,
                                     String provider)
                              throws NoSuchAlgorithmException,
                                     NoSuchProviderException
返回实现指定安全套接字协议的  SSLContext 对象。

返回一个封装 SSLContextSpi 实现的新 SSLContext 对象,该实现取自指定的提供者。指定的提供者必须在安全提供者列表中注册。

注意,可以通过 Security.getProviders() 方法获取已注册提供者列表。

参数: protocol - 所请求协议的标准名称。有关标准协议名称的信息,请参见 Java Secure Socket Extension Reference Guide 的附录 A。 provider - 提供者的名称。 返回:新的  SSLContext 对象。 抛出: NoSuchAlgorithmException - 如果不能从指定提供者获得指定协议的 SSLContextSpi 实现。 NoSuchProviderException - 如果指定提供者未在安全提供者列表中注册。 IllegalArgumentException - 如果提供者的名称为 null 或空。 另请参见: Provider

所以报错的原因应该是”SunJSSE“在Android环境下是没有注册的提供者,所以无法建立SSLContext。

 

继续查看JDK API,发现:


getInstance

public static SSLContext getInstance(String protocol)
                              throws NoSuchAlgorithmException
返回实现指定安全套接字协议的  SSLContext 对象。

此方法从首选提供者开始遍历已注册安全提供者列表。返回一个封装 SSLContextSpi 实现的新 SSLContext 对象,该实现取自支持指定协议的第一个提供者。

注意,可以通过 Security.getProviders() 方法获取已注册提供者列表。

参数: protocol - 所请求协议的标准名称。有关标准协议名称的信息,请参见 Java Secure Socket Extension Reference Guide 的附录 A。 返回:新的  SSLContext 对象。 抛出: NoSuchAlgorithmException - 如果没有提供者支持指定协议的 TrustManagerFactorySpi 实现。 另请参见: Provider 所以代码改为:
Java代码   收藏代码
  1. SSLContext sslContext = SSLContext.getInstance("SSL");  

这样会自动调用Security.getProviders()获取已经注册的提供者。


java.net.SocketException: java.security.NoSuchAlgorithmException

java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
    at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:198)
    at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:205)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

服务器从windows移植至linux上突然一些业务不能执行,追踪至抛出来的异常如上。

解决开始:

定位:

问题确实是如上的异常,本地一切正常访问,windows一切正常访问

检测是否为代码问题,是否有平台兼容性问题

此访问为http的post的请求,不访问文件,不查询数据库,请求统一为utf-8不涉及编码问题,暂时排除代码问题

检测是否平台环境问题

j通过搜索发现问java环境问题

解决:

java使用yum安装未设置java环境变量,但java -version正常执行

开始设置环境变量,设置完成 仍不能正常工作

配置并指定sunjce_provider.jar和jce.jar的classpath路径

$JAVA_HOME/lib/ext/sunjce_provider.jar:$JAVA_HOME/lib/jce.jar

并在security/java.security文件设置

security.provider.1=com.sun.crypto.provider.SunJCE
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=sun.security.ec.SunEC
security.provider.5=com.sun.net.ssl.internal.ssl.Provider
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC

完成后,重新启动服务,问题依旧

再搜索 从官网上下载 并替换security下 local_policy.jar 和 US_export_policy.jar

完成后,重新启动服务,问题依旧

百思不得其解,于是对比了本地的JRE下项目所引用的jar包,发现和服务器JRE的lib/ext下少包,于是复制jaccess.jar、sunec.jar和sunmscapi.jar至服务器JRE下lib/ext

下。问题解决。

 

总结:首先,需要错误的正确定位,再次,确认真正引起错误的原因

还有,不了解HttpClient的功能

http://blog.csdn.net/liuyanghai/article/details/7191537

 参考下面一段话:

产出密钥时经常会出现java.security.NoSuchAlgorithmException异常。如下面代码,在elipse中编译通过,但运行时会抛出java.security.NoSuchAlgorithmException异常
KeyGenerator keyGen=null;
keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);
Key key = keyGen.generateKey();
网上关于这个问题的解答不多,已有的一般是说java.security.Provider
是个abstract class,sun没有将它实现,就像jdbc一样由提供商提供;还有就是说关于密钥这一块USA对我们封锁,我们下的jdk里不带;还有就是说要往%javahome%/lib/security/java.security里添加security.provider.1=com.sun.crypto.provider.SunJCE;要确保在classpath里能找到com.sun.crypto.provider.SunJCE;用IBMJDK1.4就没有问题。
根据jdk的文档,从1.4开始就把jce集成起来了,而且在%javahome%/lib/ext里的确存在sunjce_provider.jar,里面包含了com.sun.crypto.provider.SunJCE。在elipse里运行时抛出异常的原因是,class在eclipse里运行时,是通过eclipse的进行classload时会把com.sun.crypto.provider.SunJCE的签名信息去掉,这样JCE就不认这个类了,导致找不到Provider的实现,解决办法:在eclipse的preferences->java->installed jres里选择你指定的jre,edit,将Use default system libraries选上就可以正常运行了。其实把上面的程序在eclipse里编译好,直接在命令行下run,是不会出现上面的问题的。
在eclipse里,IBMjdk可以正常使用,可能是他们密切关系的原因吧,呵呵!
在其它的一些情况下抛出java.security.NoSuchAlgorithmException的话,也可以考虑是不是在通过其它的程序进行classload时去掉了签名



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值