20220113のJavaに関する記事は3件です。

Effective Java第3版 項目26 p120に記述されているコードスニペットを完成させてみた。

 Effective Javaを読んて勉強してみようと思いましたが私にとっては難しいものでした。そこでじっくりとコードを打ち込んで理解しようと思いましたがコードが断片的であり、すんなり理解できなかったので、コードの省略部分を想像に任せ動くようにして、理解を深めようと思います。  本の1ページ目から始めればいいのですが、勉強会に途中から参加することになり、項目26から始めます。またこの記事は、記述されていない省略されたコードを補完することが目的で、何か技術的な説明をするのが目的なので、本を持っていないと理解できないことが多くあると思います。 1.本記事の対象の項目とページ 第5章 ジェネリックス 項目26 原型を使わない p120 2.コードスニペットを動くように補完したコード  p120上段部分で記述されている「やってはいけないコード」のスニペットを以下のとおり書き加えて、本書に書かれているエラーを吐き出すことができるようにしました。  次のコードは、main()メソッドを含むクラスです。本に記述されたコードスニペットを含んだStampCollectionクラスのインスタンスを生成します。 Item26_3.java // p120 item26 やってはいけないなコード public class Item26_3 { public static void main(String[] args) { StampCollection stampCollection = new StampCollection(); stampCollection.addStamp(); stampCollection.showCollection(); } }  p120に記述されたコードスニペットを補完したコードを記述したクラスです。  本の中で 「private final Collection stamps =・・・」と書かれた「・・・」の部分は、Collectionインタフェースを実装したクラスなら何でも良さそうなので、一番ポピュラーなArrayList()を選びました。試してはいませんが、他にもLinkedListクラスやHashSetクラス、TreeSetクラスでもいいと思います。もしこれらのクラスを選んだら、本クラス後半のメソッドの内容が変わると思います。この辺は「川場著 新わかりやすいJava オブジェクト指向編p342」を参照しました。 StampCollection.java public class StampCollection { // 私の切手コレクション。Stampインスタンスだけを含む。 private final Collection stamps = new ArrayList(); public void addStamp() { stamps.add(new Stamp(150, "山")); stamps.add(new Stamp(250, "川")); // 切手コレクションへのコインの誤った挿入 stamps.add(new Coin(100, "花")); // 「java: 不適合な型: CoinをStampに変換できません:コンパイルエラー } public void showCollection(){ // 原型のイテレータ型 - これをやってはいけない! for ( Iterator i = stamps.iterator(); i.hasNext(); ) { Stamp stamp = (Stamp)i.next(); //stamp.cancel(); System.out.println(stamp.toString()); } } }  上記のコードでcancel()が何か特別な意味があるのか疑問に思いteratailで質問したところ、何の意味もないとのことでしたので、コメントアウトしました。もし意味のないコードなら、悩むので記述して欲しくありませんでした。  次のStampクラスは切手コレクションのインスタンスstampsに登録する切手を表すデータクラスです。本の中では特にクラスの中身を指定していなかったので、とりあえず金額と絵柄のデータを持つことにしました。また登録したstampクラスのインスタンスの内容を表示できるようにtoString()メソッドを持っています。 Stamp.java public class Stamp { private int value; private String design; public Stamp(int value, String design){ this.value = value; this.design = design; } @Override public String toString() { return "Stamp{" + "value=" + value + ", design='" + design + '\'' + '}'; } }  次のcoinクラスは、切手コレクションに誤って登録する切手のデータクラスです。クラスの作りはStampクラスと同じです。いっそのことStampクラスとの共通部分をインタフェースにすればいいかもしれません。 Coin.java public class Coin { private int value; private String design; public Coin(int value, String design){ this.value = value; this.design = design; } @Override public String toString() { return "Coin{" + "value=" + value + ", design='" + design + '\'' + '}'; } }  これらのコードをコンパイルすると、本の記述どおり警告と実行時エラーを生じました。 [警告] [実行時エラー] 3.このようにしましょうのコードスニペット部分 本書120ページ後半に書かれている、このようにしましょうの部分。下のようにStampCollectionクラスの8行目に実パラメータを加え、 private final Collection<Stamp> stamps = new ArrayList<>(); と変更すれば、コンパイルエラーを生じることができますし、IntelliJなどのIDEを使用していればコードを書きながらエラーを見つけることができます。なぜコンパイルエラーを生じさせた方がいいかについては、本書を読んでください。  また本書には記述されていませんが、19行目を次のようにIteratorに実パラメータを加えるように変更すると、i.next()の前に記述していた(satamp)のキャストが不要になりうっかりミスがなくなります。(ArrayListの後ろの実パラメータ記述していませんが、jdkが型推論してくれるので省略しています。もちろんArrayListと記述してもよいです。) for ( Iterator<Stamp> i = stamps.iterator(); i.hasNext(); ) { Stamp stamp = i.next(); 以上、
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WebViewで基本認証させる際の注意点

最初に結論 AndroidアプリのWebViewで基本認証させようと思って検索するとよく見かけるサンプルコードについて、これではコンテンツに埋め込まれている外部サイトのオブジェクト(画像とかロギングツールとか広告オブジェクトとか)へ認証情報を流してしまうかもしれないので、注意が必要。 つまり、認証情報を提示するホスト/URLを、きちんと制限しましょう。という至極当然の結論。 よく見るサンプルコード webView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { handler.proceed("ユーザ名", "パスワード"); } }); つまり、WebViewClientクラスの「onReceivedHttpAuthRequest」をオーバーライドして、ユーザ名とパスワードを与えてあげればいい。 というもの。 まぁ、確かにそうなんだが、これでは、任意のホストの任意のレルムに認証情報を流してしまうかもしれないので、注意が必要。 実際に試してみる 環境 こんな感じ トップの192.0.2.1のコンテンツ内部に、192.0.2.2のコンテンツ(広告の画像とか、外部スクリプトとか)を参照しているような場合。 192.0.2.2 側で故意に認証要求させると認証情報がそちらに漏れるかもしれない。 アプリのコード protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // これはトップのhttp://192.0.2.1:90/Auth/test.htmqだけに // 関係する認証情報のはず、だと思ってコーディングしていると思う String username = "sanaki"; String password = "password123!"; // WebView webView = (WebView)findViewById(R.id.webView); webView.setWebViewClient(new WebViewClient(){ @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { handler.proceed(username, password); Log.i("BasicAuth", "Host=" + host + ",realm=" + realm); } }); // JavaScriptを有効化 webView.getSettings().setJavaScriptEnabled(true); // JavaScriptを有効にする // webView.loadUrl("http://192.0.2.1:90/Auth/test.htm"); } こんな感じ。 アプリを起動すると「192.0.2.1:90」にアクセスして、そのコンテンツを表示する。というやつ。 ネットにアクセスするために AndroidManifest.xmlに 「<uses-permission android:name="android.permission.INTERNET"/>」 と、(検証のためにhttpsにするのは面倒なので)平文のhttpをWebViewで許可するために 「android:usesCleartextTraffic="true"」 は記述している まぁ、基本認証をしているということは、主に管理系のWebサイトだと思うけど、管理系に広告とかアクセス履歴系のやつとか埋め込んでいるのも、まぁ、たしかに想定としておかしな話かもしれんけどねぇ~ 結果(まとめ) きちんと、192.0.2.2側にも認証情報が洩れている事が、下記から確認できると思う。 結果(ログ) Logの方には、こんな感じで、ログが出てる。 2022-01-12 15:36:06.175 18740-18740/jp.dip.rocketeer.webviewtest I/BasicAuth: Host=192.0.2.1,realm=192.0.2.1 2022-01-12 15:36:06.379 18740-18740/jp.dip.rocketeer.webviewtest I/BasicAuth: Host=192.0.2.2,realm=192.0.2.2 子フレーム側の192.0.2.2側にも認証情報が洩れているということになるだろう。 結果(192.0.2.1側{親、想定しているホスト側}) 192.0.2.1 の方は、こんな感じの通信内容となっている。 RAW 通信データ C:&gt;StreamRelay.NET.exe -localport 90 -remoteport 80 -remotehost 127.0.0.1 -logging GET /Auth/test0.htm HTTP/1.1 Host: 192.0.2.1:90 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 X-Requested-With: jp.dip.rocketeer.webviewtest Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 HTTP/1.1 401 Unauthorized ← 192.0.2.1側のこれは想定している認証要求 Cache-Control: private Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET WWW-Authenticate: Basic realm="192.0.2.1" Date: Wed, 12 Jan 2022 07:11:14 GMT Content-Length: 6396 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>IIS 10.0 エラーの詳細 - 401.2 - Unauthorized</title> <style type="text/css"> <!-- body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;} code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;} .config_source code{font-size:.8em;color:#000000;} pre{margin:0;font-size:1.4em;word-wrap:break-word;} ul,ol{margin:10px 0 10px 5px;} ul.first,ol.first{margin-top:5px;} fieldset{padding:0 15px 10px 15px;word-break:break-all;} .summary-container fieldset{padding-bottom:5px;margin-top:4px;} legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;} legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px; font-weight:bold;font-size:1em;} a:link,a:visited{color:#007EFF;font-weight:bold;} a:hover{text-decoration:none;} h1{font-size:2.4em;margin:0;color:#FFF;} h2{font-size:1.7em;margin:0;color:#CC0000;} h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;} h4{font-size:1.2em;margin:10px 0 5px 0; }#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif; color:#FFF;background-color:#5C87B2; }#content{margin:0 0 0 2%;position:relative;} .summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;} .content-container p{margin:0 0 10px 0; }#details-left{width:35%;float:left;margin-right:2%; }#details-right{width:63%;float:left;overflow:hidden; }#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF; background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal; font-size:1em;color:#FFF;text-align:right; }#server_version p{margin:5px 0;} table{margin:4px 0 4px 0;width:100%;border:none;} td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;} th{width:30%;text-align:right;padding-right:2%;font-weight:bold;} thead th{background-color:#ebebeb;width:25%; }#details-right th{width:20%;} table tr.alt td,table tr.alt th{} .highlight-code{color:#CC0000;font-weight:bold;font-style:italic;} .clear{clear:both;} .preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;} --> </style> </head> <body> <div id="content"> <div class="content-container"> <h3>HTTP エラー 401.2 - Unauthorized</h3> <h4>認証ヘッダーが無効なため、このページを表示することができません。</h4> </div> <div class="content-container"> <fieldset><h4>可能性のある原因:</h4> <ul> <li>IIS は認証プロトコル (匿名のものも含む) を選択しません。</li> <li>統合認証のみ有効です。統合認証をサポートしないクライアント ブラウザーが使用されました。</li> <li>統合認証は有効で、Web サーバーに到達する前に認証ヘッダーを変更するプロキシ サーバーをとおして要求が送信されています。</li> <li>Web サーバーは匿名アクセスに対して構成されてなく、必要な認証ヘッダーが受信されませんでした。</li> <li>"configuration/system.webServer/authorization" 構成セクションが明示的にユーザーのアクセスを拒否しています。</li> </ul> </fieldset> </div> <div class="content-container"> <fieldset><h4>対処方法:</h4> <ul> <li>リソースに対する認証設定を確認した後、その認証方法を使用するリソースを要求します。</li> <li>クライアント ブラウザーが統合認証をサポートしていることを確認します。</li> <li>統合認証が使用される場合、要求がプロキシ サーバーをとおしていないことを確認します。</li> <li>"configuration/system.webServer/authorization" 構成セクションによって、ユーザーが明示的にアクセスを拒否されていないことを確認します。</li> <li>この HTTP 状態コードに対して失敗した要求を追跡するトレース規則を作成します。失敗した要求のトレース規則の作成の詳細については、<a href="http://go.microsoft.com/fwlink/?LinkID=66439">ここ</a>をクリックします。</li> </ul> </fieldset> </div> <div class="content-container"> <fieldset><h4>エラー情報の詳細:</h4> <div id="details-left"> <table border="0" cellpadding="0" cellspacing="0"> <tr class="alt"><th>モジュール</th><td>&nbsp;&nbsp;&nbsp;IIS Web Core</td></tr> <tr><th>通知</th><td>&nbsp;&nbsp;&nbsp;AuthenticateRequest</td></tr> <tr class="alt"><th>ハンドラー</th><td>&nbsp;&nbsp;&nbsp;StaticFile</td></tr> <tr><th>エラー コード</th><td>&nbsp;&nbsp;&nbsp;0x80070005</td></tr> </table> </div> <div id="details-right"> <table border="0" cellpadding="0" cellspacing="0"> <tr class="alt"><th>要求された URL</th><td>&nbsp;&nbsp;&nbsp;http://192.168.0.11:80/Auth/test0.htm</td></tr> <tr><th>物理パス</th><td>&nbsp;&nbsp;&nbsp;C:\inetpub\Rocketeer\Auth\test0.htm</td></tr> <tr class="alt"><th>ログオン方法</th><td>&nbsp;&nbsp;&nbsp;未定義です</td></tr> <tr><th>ログオン ユーザー</th><td>&nbsp;&nbsp;&nbsp;未定義です</td></tr> </table> <div class="clear"></div> </div> </fieldset> </div> <div class="content-container"> <fieldset><h4>詳細情報:</h4> このエラーは、Web サーバーに送信された WWW-Authenticate ヘッダーがサーバーの構成でサポートされていないときに発生します。リソースの認証方法を確認し、クライアントが使用している認証方法を確認します。それらの認証方法が異なる場合、このエラーが発生します。クライアントが使用している認証の種類を判断するには、クライアントの認証設定を確認します。 <p><a href="https://go.microsoft.com/fwlink/?LinkID=62293&amp;IIS70Error=401,2,0x80070005,17763">詳細情報の表示 &raquo;</a></p> <p>マイクロソフト サポート技術情報の記事:</p> <ul><li>907273</li><li>253667</li></ul> </fieldset> </div> </div> </body> </html> GET /Auth/test0.htm HTTP/1.1 Host: 192.0.2.1:90 Connection: keep-alive Authorization: Basic c2FuYWtpOnBhc3N3b3JkMTIzIQ== ← これは想定している認証情報 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 X-Requested-With: jp.dip.rocketeer.webviewtest Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 HTTP/1.1 200 OK Content-Type: text/html Last-Modified: Wed, 12 Jan 2022 06:47:42 GMT Accept-Ranges: bytes ETag: "e418764c807d81:0" Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET Date: Wed, 12 Jan 2022 07:11:14 GMT Content-Length: 157 <html> <head><title>Basic Auth Test</title></head> <body>This is Test <hr> <iframe src="http://192.0.2.2/Auth/testIn.htm"></iframe> </body> </html> 結果(192.0.2.2側{子、想定していないホスト側}) 192.0.2.2 の方は、こんな感じの通信内容となっている。 認証情報が漏れている事が確認できる RAW 通信データ C:&gt;StreamRelay.NET.exe -localport 80 -remoteport 80 -remotehost 192.0.2.1 -logging GET /Auth/testIn.htm HTTP/1.1 Host: 192.0.2.2 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 X-Requested-With: jp.dip.rocketeer.webviewtest Referer: http://192.0.2.1:90/Auth/test0.htm Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 HTTP/1.1 401 Unauthorized ← 192.0.2.2側のこちらは想定されていない場面が多いと思う Content-Type: text/html Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET WWW-Authenticate: Basic realm="192.0.2.2" Date: Wed, 12 Jan 2022 07:11:14 GMT Content-Length: 1313 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"/> <title>401 - 権限がありません: 資格情報が無効であるため、アクセスが拒否されました。</title> <style type="text/css"> <!-- body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}fieldset{padding:0 15px 10px 15px;}h1{font-size:2.4em;margin:0;color:#FFF;}h2{font-size:1.7em;margin:0;color:#CC0000;}h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;background-color:#555555;}#content{margin:0 0 0 2%;position:relative;}.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;} --> </style> </head> <body> <div id="header"><h1>サーバー エラー</h1></div> <div id="content"> <div class="content-container"><fieldset> <h2>401 - 権限がありません: 資格情報が無効であるため、アクセスが拒否されました。</h2> <h3>指定した資格情報を使用して、このディレクトリまたはページを表示するアクセス許可がありません。</h 3> </fieldset></div> </div> </body> </html> GET /Auth/testIn.htm HTTP/1.1 Host: 192.0.2.2 Connection: keep-alive Authorization: Basic c2FuYWtpOnBhc3N3b3JkMTIzIQ== ← 想定外のホスト(192.0.2.2)へ認証情報が洩れている Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 X-Requested-With: jp.dip.rocketeer.webviewtest Referer: http://192.0.2.1:90/Auth/test0.htm Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 HTTP/1.1 200 OK Content-Type: text/html Last-Modified: Wed, 12 Jan 2022 04:31:28 GMT Accept-Ranges: bytes ETag: "d424f3436d7d81:0" Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET Date: Wed, 12 Jan 2022 07:11:14 GMT Content-Length: 19 This is ifame page. まとめ まぁ、つまり、オーバーライドする際に、hostやrealmで制限する必要があるということ。 例えば、 webView.setWebViewClient(new WebViewClient(){ String relmStr = ""; @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { // hostやrealmをチェックして、認証情報をチェックする必要がある if(host.equals("192.0.2.1") == true){ // 例えば、ホストで制限する if(this.relmStr.length() == 0){ // ここは一番最初の要求 this.relmStr = realm; handler.proceed("ユーザ名", "パスワード"); // ← 想定している範囲内だけに制限することが大切 }else if(this.relmStr.equals(realm) == true){ // 2番目からは記憶しているレルムの時だけに制限する handler.proceed("ユーザ名", "パスワード"); // ← 想定している範囲内だけに制限することが大切 }else{ handler.cancel(); } }else{ handler.cancel(); } } }); こんな感じ。 192.0.2.2側ではちゃんと認証情報を漏らさずに認証エラーとなっている RAW 通信データ C:&gt;StreamRelay.NET.exe -localport 80 -remoteport 80 -remotehost 192.0.2.1 -logging GET /Auth/testIn.htm HTTP/1.1 Host: 192.0.2.2 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86 Build/RSR1.201013.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 X-Requested-With: jp.dip.rocketeer.webviewtest Referer: http://192.0.2.1:90/Auth/test0.htm Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 If-None-Match: "d424f3436d7d81:0" If-Modified-Since: Wed, 12 Jan 2022 04:31:28 GMT HTTP/1.1 401 Unauthorized Content-Type: text/html Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET WWW-Authenticate: Basic realm="192.0.2.2" Date: Thu, 13 Jan 2022 00:46:32 GMT Content-Length: 1313 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-s trict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"/> <title>401 - 権限がありません: 資格情報が無効であるため、アクセスが拒否されました。</title> <style type="text/css"> <!--body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE; }fieldset{padding:0 15px 10px 15px;}h1{font-size:2.4em;margin:0;color:#FFF;}h2{font-size:1.7em;margin:0;color:#CC0000;}h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;background-color:#555555;}#content{margin:0 0 0 2%;position:relative;}.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}--> </style> </head> <body> <div id="header"><h1>サーバー エラー</h1></div> <div id="content"> <div class="content-container"><fieldset> <h2>401 - 権限がありません: 資格情報が無効であるため、アクセスが拒否されました。</h2> <h3>指定した資格情報を使用して、このディレクトリまたはページを表示するアクセス許可がありません。</h 3> </fieldset></div> </div> </body> </html> ここから通信が途切れて、最終的に認証エラーとなっている(認証情報は漏れなくなった) これでも、悪意あるコンテンツと、レンタルサーバを共有しているような場合は、突破されるので、さらなる制限が必要だよ。 (第一引数のWebView viewを使ってポートとか、URLのパスとかに基づいてさらに制限をかける) リンク JSSECの「Androidアプリのセキュア設計・セキュアコーディングガイド」は読んでおこう。 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaでとりあえずWeb APIを叩く方法

JavaでAPIを叩く方法でつまづいたので書き記す とりあえず公開されているAPIを叩きたい人向け もっといい方法ありそうですが書いておきます importするライブラリ import java.net.URL; import java.io.*; コード final String endpoint = "任意のURL";                 // ここではkeyとidのパラメータが必要な場合を書きます。必要ない人は飛ばしてください。 final String key = "パラメータ必要な人は"; final String Id = "任意で";                 // パラメータが複数ある人はidのように&で繋げてください。 String url = endpoint + "?key=" + key + "&id=" + Id; URL obj = new URL(url); InputStreamReader streamReader = new InputStreamReader( obj.openStream() ); BufferedReader bufferedReader = new BufferedReader( streamReader ); String content = bufferedReader.readLine() System.out.println(content);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む