- PR -

URL openConnection()で止まってしまう。

投稿者投稿内容
トラジャ
ベテラン
会議室デビュー日: 2002/12/05
投稿数: 75
投稿日時: 2004-10-15 15:17
いっきゅうさん、ありがとうございます。

それから、おばけさんも本当にありがとうございます。いちおう、アドレスはIPで
設定しているので、名前解決は問題ないかと思っています。

引用:

根本的なこと確認したいのですが
運用環境で用いられているJavaのバージョンは何でしょうか?
その上でFreeBSDのJavaのそのリリースでそういったバグは無いのか
調べておいた方がいいのではないでしょうか。
後、BsdでJavaを動かす場合のパッチもちゃんと当てているのか
確認してみてはどうでしょうか?



Javaのバージョンは、"1.4.2-p6"でした。パッチやバグについては調べています。

引用:

後、次は確認したのでしょうか?
・運用サーバと決済サーバ間にFirewallはあるのか。
 あるならproxyの設定はしているのか。
(次は今まで確認しているのはTomcatから呼び出していると判断した上で)
・スタンドアローンでHttpURLConnectionで接続した場合。
・スタンドアローンでSocketで接続した場合。
・TomcatでSocketで接続した場合。
これにそれぞれ接続先をHttpとHttpsの両方確認。

以上のような事を私なら最低限確認しようと思います。




はい。さっそくご提案に従い、いくつかの方法を試してみました。

HTTPs
1.Tomcat + URLConnection = ×
2.Tomcat + SSLSocket = ×
3.スタンドアローン + URLConnection = ×

HTTP
1.Tomcat + URLConnection = ○
2.Tomcat + SSLSocket = ○
3.スタンドアローン + URLConnection = ○

ということで、どうやら"HTTPs"だけ接続できないみたいです。

そうなると、サーバー自体の設定が何か必要なようなのですが、"HTTPs"接続を
できるようにするためには、サーバーのどこをどのように設定する必要があるのでしょうか。ハード的なことについてはまだ勉強不足なものですから。

私自身はサーバーの管理まではしていないのですが、こちらのプログラムに問題がない
ことを証明した上で、サーバーのどこを設定する必要があるのか指摘しないと納得して
もらえそうにないのです。

だいぶ原因が絞られてきましたので、あともう一息、どなたか助けていただけませんで
しょうか。

よろしくお願いします。
いっきゅう
大ベテラン
会議室デビュー日: 2004/04/04
投稿数: 153
お住まい・勤務地: 兵庫
投稿日時: 2004-10-15 18:27
Httpsの問題なら認証する際の問題みたいに見えるのですが
信頼できない証明書や証明書とサーバの名前解決で
Exceptionが発生しているわけではないですよね?
もし、上記処理に問題(バグ?)あるとするなら
下記のようなコードをコネクションを張る前に呼んで
無視するようにしてみてはどうでしょうか?
コード:
TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

HostnameVerifier allhost = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init( null, trustAllCerts,new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    HttpsURLConnection.setDefaultHostnameVerifier(allhost);
}
catch (Exception e) {
    e.printStackTrace();
}

unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-10-15 19:15
unibon です。こんにちわ。

詳しいことは知らないのですが、もし可能ならば接続先を別の Web サーバーにしてみてはどうでしょうか。たとえば Yahoo! とかのサイトに(Yahoo! はあくまでも一例でしかありませんが)。もし現在の問題の原因が証明書まわりにあるのならば、他の著名なサイトならば接続できるはずです。
トラジャ
ベテラン
会議室デビュー日: 2002/12/05
投稿数: 75
投稿日時: 2004-10-15 19:20
いっきゅうさん、ありがとうございます。

実は、サーバー認証を無視するサンプルを見つけたので、それを利用しているのですが、一休さんの教えてくださったのと同じ方法みたいです。

でも、問題はそこに行く前のところで止まっているみたいなのです。

実際の接続処理のメソッドの中身は以下のようになっています。
このメソッドで作成したコネクションでデータの入出力ストリームを作成しています。

try
{
URL u = new URL("https://IP Address/xxx/xxx?xxx=xxx");
System.out.println("Try openConnection");
↑ ここまで出力ログに記録されている

URLConnection hCon = u.openConnection();
↑問題の箇所
ここでURLConnectionのインスタンスを取得するときに止まっている
エラーも何もスローされない
しばらく放置してもタイムアウトにもならない

System.out.println("URL openConnection:" + url);
↑ これは出力ログに記録されない

// 入出力設定
hCon.setDoOutput(true);
//******************************************************************
SSLSocketFactory sslsf = null;
KeyManager[] km = null;
//サーバーの証明書を強制的に認証させる
TrustManager[] tm = { new RelaxedX509TrustManager() };
//ソケットプロトコルを実装するSSLContextを作成
SSLContext sslContext = SSLContext.getInstance( "SSL" );
//SSLContextを初期化
sslContext.init( km, tm, new SecureRandom() );
//SSLContextのSocketFactoryを取得
sslsf = sslContext.getSocketFactory();
//URLConnectionにSocketFactoryをセット
( ( HttpsURLConnection )hCon ).setSSLSocketFactory( sslsf );
//******************************************************************
//ホスト名を無視させる
HostnameVerifier hv = new HostNameVeri();
( ( HttpsURLConnection )hCon ).setHostnameVerifier(hv );
System.out.println("SSL connected");
}
catch(Exception e)
{
System.out.println(e);
throw new CreditCardException();
}
いっきゅう
大ベテラン
会議室デビュー日: 2004/04/04
投稿数: 153
お住まい・勤務地: 兵庫
投稿日時: 2004-10-16 18:25
トラジャさんの見つけた方法についても私も参考したことがあります。
その方法ですとJSSE1.0.3での方法でJ2sdk1.4以降だと
コンパイル時警告がでませんか?
私の方法は1.4で対応したものです。
Windowsですとどちらの方法でも問題なかったですが
FreeBSDでもそうなのかは分からないですが、、


後、URLConnection hCon = u.openConnection(); を
呼ぶ前にサーバー認証を無視するコードを呼ばないと意味が無いと
思うのですが、
確認していませんが別環境で動いていたんでしょうか?

//// 修正追加 ここから
setDefault***の場合は初期化する前で
setHostnameVerifier() とsetSSLSocketFactory()の場合
初期化したHttpsURLConnectionに直接設定するので
初期化後でも通信前までならいいみたいですね。
ちょっと間違えていたので補足します。
//// 修正追加 ここまで

[ メッセージ編集済み 編集者: いっきゅう 編集日時 2004-10-16 18:55 ]
トラジャ
ベテラン
会議室デビュー日: 2002/12/05
投稿数: 75
投稿日時: 2004-10-17 00:26
引用:

その方法ですとJSSE1.0.3での方法でJ2sdk1.4以降だと
コンパイル時警告がでませんか?
私の方法は1.4で対応したものです。
Windowsですとどちらの方法でも問題なかったですが
FreeBSDでもそうなのかは分からないですが、、



参考にさせていただいたのは、以下のサイトでした。
http://shinjuku.cool.ne.jp/kiuma/java/java/https.html

このページの最後に「com.sun.net.sslとなっているパッケージはjavax.net.sslに
変わっています。」と書いてあったので、importするパッケージを"javax.net.ssl"
にしたらコンパイルエラーは出ませんでした。

それから、"SSLSocket"を使って試した際のコードは以下のとおりです。

SSLSocketFactory sslsf = null;
KeyManager[] km = null;
//証明書の信頼性を決定するためのインターフェース
TrustManager[] tm = { new RelaxedX509TrustManager() };
//ソケットプロトコルを実装するSSLContextを作成
SSLContext sslContext = SSLContext.getInstance( "SSL" );
//SSLContextを初期化
System.out.println("Start SSLContext.init");
↑ここまでログに出力されている

sslContext.init( km, tm, new SecureRandom() );
↑ここで止まってしまっているみたい

System.out.println("End SSLContext.init");
↑ここはログに出力されない

//SSLContextのSocketFactoryを取得
sslsf = sslContext.getSocketFactory();
Socket socket = sslsf.createSocket("IP Address",443);

上記のように、Socketを使った場合、sslContext.init()で止まってしまいます。

URL.openConnection()とSSLContext.init()は同じ処理をしているのでしょうか?
トラジャ
ベテラン
会議室デビュー日: 2002/12/05
投稿数: 75
投稿日時: 2004-10-19 09:01
少し進展がありました。

SSLSocketによる接続をテストしていましたところ、なぜか1回目の接続はうまく
いかないのですが、2回目からは
sslContext.init( km, tm, new SecureRandom() );
で止まることなく、Socketを作るところまでいくようになりました。

ただ、そのSocketを使って実際に送信処理をした直後に、以下のExceptionが発生
します。これの意味がいろいろ探してみたのですが、いまいち分かりません。

javax.net.ssl.SSLProtocolException: java.io.IOException: java.io.IOException: Host portion is not a valid DNS name, IPv4 address, or IPv6 address
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateMsg.<init>(DashoA6275)
at com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA6275)
at com.sun.net.ssl.internal.ssl.SunJSSE_ax.a(DashoA6275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(DashoA6275)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(DashoA6275)
at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:336)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:404)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:408)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:152)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:213)
at jp.genux.ireserve.entry.CreditExamination.sendPostData(CreditExamination.java:165)
at jp.genux.ireserve.struts.entry.RegReserveAction.execute(RegReserveAction.java:82)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:284)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:204)
at filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:169)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:233)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:204)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:257)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:567)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:245)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:199)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:567)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:184)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:164)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:149)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:567)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:156)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:567)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:972)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:206)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:833)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:732)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:619)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:688)
at java.lang.Thread.run(Thread.java:534)
Caused by: java.security.cert.CertificateParsingException: java.io.IOException: java.io.IOException: Host portion is not a valid DNS name, IPv4 address, or IPv6 address
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:157)
at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1679)
at sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:173)
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:90)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:389)
... 47 more
Caused by: java.io.IOException: java.io.IOException: Host portion is not a valid DNS name, IPv4 address, or IPv6 address
at sun.security.x509.CertificateExtensions.parseExtension(CertificateExtensions.java:111)
at sun.security.x509.CertificateExtensions.init(CertificateExtensions.java:78)
at sun.security.x509.CertificateExtensions.<init>(CertificateExtensions.java:57)
at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:731)
at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:155)
... 51 more
Caused by: java.io.IOException: Host portion is not a valid DNS name, IPv4 address, or IPv6 address
at sun.security.x509.URIName.parseName(URIName.java:205)
at sun.security.x509.URIName.<init>(URIName.java:85)
at sun.security.x509.GeneralName.<init>(GeneralName.java:94)
at sun.security.x509.GeneralNames.<init>(GeneralNames.java:51)
at sun.security.x509.DistributionPoint.<init>(DistributionPoint.java:193)
at sun.security.x509.CRLDistributionPointsExtension.<init>(CRLDistributionPointsExtension.java:126)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
at sun.security.x509.CertificateExtensions.parseExtension(CertificateExtensions.java:105)
... 55 more
トラジャ
ベテラン
会議室デビュー日: 2002/12/05
投稿数: 75
投稿日時: 2004-10-21 19:39
みなさん、たいへんお世話になりました。

すべて解決いたしましたので、他の方々の参考にでもなればと以下に、解決手順
をお知らせいたします。

■HTTPs通信時、URL.openConnectionで止まるエラー。

◎Java起動オプションまたはCATALINA_OPTに
"-Djava.security.egd=file:/dev/urandom"を設定する。

参考文献URL
http://sirius.itfrontier.co.jp/kb/cf_article.cfm?TYPE=en&ID=19127

これは、Java Virtual Machine (JVM) の SecureRandom() コールのシーディング中に /dev/random デバイスにより、 I/O がブロックされてしまうことが原因です。ColdFusion MX がスタートアップ/再起動後に呼び出される最初の cfapplication タグの cftoken 値を作成する時、JVM は java.Security.SecureRandom を開始します。SecureRandom は暗号的に強力な乱数ジェネレータであり、シーディング ソースとして特別な /dev/random デバイスを使用します。ランダム バイトのリクエストされた数を返すのに十分なインターフェースのために収集されるエントロピーがあるまで、/dev/random デバイスは I/O をブロックします。

SecureRandom は 1.3.x SDK のオプション パッケージと 1.4.x SDK で統合される今、J2EE Java Authentication と Authorization Service (JAAS) の一部です。JVM は 2 つのエントロピー デバイス (EGD) を許可します: /dev/random と /dev/urandom。通常、ColdFusion MX はデバイスを必要としませんが、あれば JVM はそれを使用しようとします。java.security マスター プロパティ ファイルはデフォルトで /dev/random になります。

対応方法:

この問題を避けるために、JVM が /dev/urandom デバイスを使用するようにします。そのために、以下のオプションの 1 つを使用します:

cf_root/runtime/jre/lib/security/java.security ファイルを編集します。このエントリを変更してください:

securerandom.source=file:/dev/random

変更後

securerandom.source=file:/dev/urandom

- または -


ColdFusion Administrator を介して、あるいは cf_root/runtime/bin/jvm.config ファイルの java.args エントリの終わりに JVM 引数として
-Djava.security.egd=file:/dev/urandom を追加します。

■HTTPs接続で、SSLハンドシェーク時に"javax.net.ssl.SSLProtocolException: java.io.IOException: java.io.IOException: Host portion is not a valid DNS name, IPv4 address, or IPv6 address "エラーが発生する。

どうやら、FreeBSDのNative jdkのAPIは、linux版と違うみたいです。それで少々
不安はありましたが、いくつかのlinux版のAPIライブラリをFreeBSD Native jdk
のライブラリと入れ替えてみました。

そうしたら、上記のエラーが発生しなくなりました。

1.linux-sun-jdk(linuxエミュレータ版)をインストールする
2.インストールした"linux-sun-jdk"の以下のJarファイルをFreeBSD Native jdkのJarファイルにコピーする。
  linux-sun-jdk/lib/tools.jar
  linux-sun-jdk/jre/lib/jsse.jar
  linux-sun-jdk/jre/lib/rt.jar(このJarをコピーするだけでもエラーが消えるかもしれない)

■参考

1.HTTPs通信時のやりとりをdebugで表示させる方法

参考文献URL
http://www.techfirm.co.jp/manual/jdk14ja/guide/security/jsse/JSSERefGuide.html


デバッグメッセージをすべて表示する場合は、次のように入力します。
java -Djavax.net.debug=all MyApp


ハンドシェークメッセージを 16 進ダンプで表示するには、次のように入力します。コロンは省略できます。
java -Djavax.net.debug=ssl:handshake:data MyApp


ハンドシェークメッセージを 16 進ダンプで表示し、さらにトラストマネージャのトレース状態を表示するには、次のように入力します。カンマは省略できます。
java -Djavax.net.debug=SSL,handshake,data,trustmanager MyApp

現在のオプションは次のとおりです。

all turn on all debugging
ssl turn on ssl debugging

The following can be used with ssl:
record enable per-record tracing
handshake print each handshake message
keygen print key generation data
session print session activity
defaultctx print default SSL initialization
sslctx print SSLContext tracing
sessioncache print session cache tracing
keymanager print key manager tracing
trustmanager print trust manager tracing

handshake debugging can be widened with:
data hex dump of each handshake message
verbose verbose handshake message printing

record debugging can be widened with:
plaintext hex dump of record plaintext

2.HTTPs通信時にサーバー認証を無視して強制的に認証させる方法

参考文献URL
http://shinjuku.cool.ne.jp/kiuma/java/java/https.html



[ メッセージ編集済み 編集者: トラジャ 編集日時 2004-10-21 19:42 ]

スキルアップ/キャリアアップ(JOB@IT)