- 投稿日:2019-04-03T23:09:56+09:00
JSPのformのパス
サーブレット・JSP formのパス
formのactionのパスについて
eclipseにて開発中ですが
formのパスで悩んだので記録test.jsp
から
サーブレットクラスの
RetweetBot2.java
foo.java
にパラメータを送信したい時のパス
RetweetBot2.javafoo.javaの修飾名は下記のものです。
/sample/src/pkg/foo.java↓のコードだと404エラー
test.jsp<form action="/sample/src/pkg/foo" method="post"> <p>送信したいテキストを入力して下さい: <input type="text" name="hoge"></p> <input type="submit" value="送信"> </form>。。。。
↓のコードだと送信成功しました。
test.jsp<form action="/sample/foo" method="post"> <p>送信したいテキストを入力して下さい: <input type="text" name="hoge"></p> <input type="submit" value="送信"> </form>理由は勉強中です。まだ不明です。
理解できたら追記予定です。
・2019/04/06 修正
サーブレットクラス名に誤りがあった為
(誤)RetweetBot2.java → (正)foo.java
に修正しました。
- 投稿日:2019-04-03T22:43:15+09:00
ifとswitchどっちがいいのか問題
はじめに
- みなさんコーディングをしてきて、今までに何回ifを書いてきましたか?笑
- 何万回と書いていても、たまにswitchを使うかifを使うか悩みますよね??(僕は悩むことがあります)
今の僕の選択基準
- if文を選ぶとき:&&とか||したいとき
- switchするとき:選択肢がいっぱいあるとき
- switchするまでもないとき:三項演算子
- あとは悩んだら感覚
- てな感じで選んでたわけなんですが、ある日僕は思いました
どっちでもかけるときってどっちがパフォーマンス出るんだろう?
- 気になったら計測すればいいんじゃね?と思い立ちます
- いざ、実行!
用意したもの
- Java1.8
- IntelliJ IDEA
目次(目次を書いてる時点でやる想定のもの)
- 100回くらいのループで分岐を走らせる
- 100回で性能差が出なかったら、桁数を1つずつ増やしていく
- ある程度満足したら、条件を増やしていく
- 条件増やすのにも満足したら、文字列と数字のパターンをやる
- こんな感じでやります
実践
100回くらいのループで分岐を走らせる
- 実行したコードは下記
CheckPerformance.javaimport java.util.stream.IntStream; public class CheckPerformance { public static void main(String[] args) { Long start = System.currentTimeMillis(); // if実行分 IntStream.rangeClosed(0, 100).forEach(i -> { if (i % 2 == 0) { System.out.println("偶数です"); } else if (i % 2 == 1) { System.out.println("奇数です"); } else { System.out.println("その他です"); } }); // switch実行分 IntStream.rangeClosed(0, 100).forEach(i -> { switch (i % 2) { case 0: System.out.println("偶数です"); break; case 1: System.out.println("奇数です"); break; default: System.out.println("その他です"); break; } }); Long end = System.currentTimeMillis(); System.out.println(end - start + "ms"); } }
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 7ms 12ms 2回目 15ms 10ms 3回目 13ms 12ms 4回目 8ms 15ms 5回目 10ms 10ms 検証
- 他にも何回か実行したが、運ゲーみたいになったので100回では性能差を検証するのは難しいと判断
- 要するに誤差でしかない
1,000回のループで分岐を走らせる
- ソースは省略
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 36ms 39ms 2回目 33ms 35ms 3回目 31ms 28ms 4回目 38ms 39ms 5回目 38ms 34ms 検証
- うーん、1,000回でも性能差を検証するのは微妙
- ここでもまだ、誤差の範疇な気がする
10,000回のループで分岐を走らせる
- ソースは(ry
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 133ms 119ms 2回目 147ms 136ms 3回目 116ms 121ms 4回目 135ms 130ms 5回目 128ms 136ms 検証
- うーん、10,000回でも...(ry
100,000回のループで分岐を走らせる
- ソースは(ry
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 903ms 917ms 2回目 947ms 885ms 3回目 1012ms 964ms 4回目 1109ms 947ms 5回目 943ms 884ms 検証
- 100,000回でちょっとだけ性能差がでた気がします
- switchが1秒超えたのが0回だったのに対して、ifは2回ありますね。
- とはいえ、誤差っちゃ誤差なのかもしれないし、平均値だけみるとswitchの方が早いのかも?って仮説はたちました
- でも、ちょっと不安なのでもう1桁だけ増やして実行しておきます
1,000,000回のループで分岐を走らせる
- s..(ry
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 6366ms 6339ms 2回目 6410ms 6396ms 3回目 6794ms 6298ms 4回目 6730ms 6248ms 5回目 6823ms 6495ms 検証
- 1,000,000回での性能差はご覧の通りです
- switchの方が速度にばらつきが無かった気がするのと、やっぱり若干ですが早いという結果に
- とはいえ、100万件やってようやくこれだけしか性能差が出ないんで、普段使いで性能差を意識することはなかなかなさそうですかね
分岐を増やしていく
- では、ある程度満足したので分岐を増やしていきます
- ここからは100件でやってもあまり意味がないことがわかったので100万件で実施していきます
まずは分岐を3つにする
- ソースは省略します
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 6348ms 6476ms 2回目 6751ms 6354ms 3回目 6461ms 6324ms 4回目 6500ms 6411ms 5回目 6537ms 6646ms 検証
- 分岐3回での性能差はご覧の通りです
- 平均値でみたときにはswitchの方が、やっぱり若干ですが早いですかね
- とはいえ、誤差なのかもしれないので分岐を増やします
分岐を5つにする
- 5つにしたのは計算の都合上と気分です
- 実行結果は下記です
X回目 ifの実行秒数 switchの実行秒数 1回目 6528ms 6279ms 2回目 6452ms 6507ms 3回目 6661ms 6599ms 4回目 6501ms 6589ms 5回目 6608ms 6322ms 検証
- 分岐5回での性能差はご覧の通りです
- うーん誤差の範囲内ですかね。
結論
ifとswitchは性能差はほとんどない!
- タイトルで釣っておいてあれなんですが、僕なりの結論です
- 100万件しか実行してないのですが、もっと増えれば変わる可能性はあるかもなのは重々承知してます
- とはいえ、分岐の数や処理件数でifとswitchでパフォーマンスが顕著に変わることはないっぽいので、その時々に合わせて読みやすくなる実装を選択するという判断が正しい気がします
- 何かおかしいだろとか、もっとこんな検証した方がいい等々あればコメントでも編集リクエストでもください!
- 投稿日:2019-04-03T20:30:12+09:00
【Java】インスタンスメソッド、インスタンスフィールド、クラスメソッド、クラスフィールド、コンストラクタまとめ
Javaを学んでいく中で結構混乱した部分をまとめます。
参考にしているのはProgateです。1.インスタンスメソッド
インスタンスメソッドはインスタンスが持つ・インスタンスに持たせる「振る舞い」。
メソッドの定義の仕方
public <戻り値の型> <メソッド名>(){ <メソッドの中身> }のように書く。
メソッドの呼び出し方
/* Personクラスのインスタンス、person1を作成 */ Person person1 = new Person(); /* helloメソッドの呼び出し */ person1.hello();のように呼び出す。
2.インスタンスフィールド
インスタンスフィールドはインスタンスが持つ情報を格納する変数。
インスタンスフィールドの定義の仕方
class Person { /* 変数なので型を宣言する */ public String name; }インスタンスフィールドのアクセス方法
/* インスタンスを生成 */ Person person1 = new Person(); /* nameに値をセット */ person1.name = "Suzuki"; /* nameの値を取得 */ System.out.println(person1.name);このようにアクセスできる。
3.クラスメソッド
クラスに属するメソッド。
クラスメソッドの定義の仕方
class Person { public static <戻り値の型> <メソッド名>() { <メソッドの中身> } }※インスタンスメソッドと異なり、
static
をつけることに注意。クラスメソッドの呼び出し方
<クラス名>.<メソッド名>();このように呼び出す。
親の顔ほど見たpublic static void <メソッド>(){ }
は実はクラスメソッドのこと。4.クラスフィールド
クラスに属するフィールド。
クラスに持たせる情報を格納する変数。クラスフィールドの定義の仕方
class Person { public static <データ型> <変数名>; }※インスタンスフィールドと異なり、
static
をつけるクラスフィールドへのアクセス方法
Main.javaclass Main { public static void main(String[] args) { System.out.println("合計" + Person.count + "人です"); Person person1 = new Person( ... ); System.out.println("合計" + Person.count + "人です"); } }Person.javaclass Person { /* countという変数に人数という情報を格納していく */ public static int count = 0; ......... Person(String firstName, ...) { Person.count ++; } }> 合計0人です > 合計1人です※インスタンス生成のたびに
count
に1ずつ足していっている5.コンストラクタ
new
でインスタンスを生成後自動で呼び出されるメソッド。
定義方法が決まっているので注意コンストラクタの定義方法
class Person { public String name; Person() { /* インスタンス生成時行いたい処理 */ } }インスタンス生成時に、インスタンスフィールドにセットしたい値をコンストラクタの引数に渡す
Person.javaclass Person { public String name; Person(String name) { this.name = name; } }コンストラクタの呼び出し方
Main.javaPerson person = new Person("Suzuki"); System.out.println(person.name);6.まとめ
修飾子 static データ型 メソッド名orフィールドの変数名 メソッド名 インスタンスメソッド public - データ型 メソッド名 インスタンスフィールド public - データ型 フィールドの変数名 クラスメソッド public static データ型 メソッド名 クラスフィールド public static データ型 フィールドの変数名 コンストラクタ public - データ型 変数名 クラス名 混乱しやすいですね!
以上です!
- 投稿日:2019-04-03T13:43:57+09:00
Authleteを使った認可サーバの構築手順(CIBA対応版)
OAuth/OpenID Connect の CIBA (Client Initiated Backchannel Authentication)ってなに
3/28(木)に開催された「OAuth & OIDC 勉強会(FAPI & CIBA 特集!) 」へ行ってきました。
主催はAuthlete社という、OAuthやOpenID Connect(以下OIDC)の認可サーバを構築できるBaasを提供する企業です。そのAuthlete社のクラウドサービスが、OAuth/OIDCの新仕様である CIBAに対応したということで、そのクラウドサービスの紹介もかねた勉強会でした。
わたくしOAuthはともかく、CIBAは初見だったので、むちゃくちゃ勉強になりました。勉強会を主催されたAuthlete社の方々、ありがとうございました。
今回はFAPI(Financial-grade API) とCIBA(Client Initiated Backchannel Authentication) についてだったのですが、FAPIに関しては「金融業界などのよりセキュリティ要件が高いところでOAuth/OIDCを使うときの制約事項」が仕様化されたモノと考えればよさそう。わかりやすい例だと、トークンを取るときのOAuth Clientのクライアントの認証はBasic認証はダメでX.509の証明書を用意してね、などなど。。
またCIBAとは、OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 のことで、いままでのOAuth/OIDC(いわゆるRFC 6749)が WEBブラウザのリダイレクトを用いる前提の処理シーケンスだったのに対し1、CIBAではバックチャネル認証エンドポイントに認証リクエストを送ると、事前に登録していたユーザの認証デバイスに「同意する?」って通知がとぶという処理シーケンスになってるのが特徴です。。
これによってたとえば、
- Alexaに「xxxを買うから¥3,000払っといて!」というと、Alexaアプリが認可サーバに認証リクエストを送り
- 認可サーバは「許可する?」って通知を認証デバイスに(スマホアプリ)に通知して
- ユーザがスマホでOKを押せば、決済が完了する
なんていう、ブラウザのリダイレクトが不要な処理シーケンスが実現できるというわけです。うーん、なるほど便利です。
具体的な処理シーケンスは、だいたいこんな感じになりそうですね。。
イントロ
さて以前、とある開発案件でAuthleteサービスをさわれる機会がありまして、そのときの構築手順をHelloWorld程度ですがQiita に投稿しました。
今回はラッキーにもCIBA対応したAuthleteサービスをさわる機会をいただきましたので、備忘として構築手順を記録しておきます。(感謝です!)
前提知識
下記の構築手順を読む上での前提知識ですが、ある程度OAuth/OIDC とCIBAをしってる前提で話を進めます。たとえば、Authorization Code Grant Flow やCIBA Flowの処理シーケンスをだいたい知ってる、などです。
さて下記は、Authorization Code Grant Flow いわゆる OAuth Danceな処理シーケンスです。Authleteの位置づけも一緒に書いています。
- Authorization Code Grant Flow の処理シーケンス
今回はCIBA対応されたAuthleteをさわるってことで、下記のような(さきほど載せた) CIBA Flowの処理シーケンスを実装してアクセストークンを取得するところまでをやってみます。認証デバイスについては、認証デバイスのシミュレータサイトがあるので、そのサイトを使用します。
- CIBA Flowの処理シーケンス
また「ユーザが認証デバイスでオペした結果(認可・拒否・タイムアウトetc.)」をOAuth Clientが知る方法としてpoll,pingもしくはpushという3つのモードがあるのですが、今回は「poll」を使います。このモードはOAuth Clientが認可サーバへポーリングすることで、ユーザのオペ結果を知るという方法です。ping,pushはまだ試してないのですが、pingの場合は認可サーバから「取りに来てイイよ」っていうHTTPSでの通知が来る、pushはそのままアクセストークンが送られてくるようですね。(参考: 9. Client Notification Endpoint )
前提環境
今回構築する環境まわりは以下の通りです。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.4 BuildVersion: 18E226
$ java -version java version "1.8.0_91" Java(TM) SE Runtime Environment (build 1.8.0_91-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)$ mvn --version Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00) $$ curl --version curl 7.54.0 (x86_64-apple-darwin18.0) libcurl/7.54.0 LibreSSL/2.6.5 zlib/1.2.11 nghttp2/1.24.1 $$ jq --version jq-1.6 $上記でやってますが、mavenとcurl, jq (とgit)が動けば、OS含めなんでもOKだと思います。
準備
また、各種サーバなど登場人物ですが、前回記事では
用途 サーバ名 URL 認可サーバ。ユーザIDごとの認可情報を管理するサーバ。 java-oauth-server http://oauth.example.com:8080/ リソースサーバ。ユーザIDごとのデータや機能をもったサーバ。 java-resource-server http://resource.example.com:8081/ Webアプリケーション。リソースサーバのリソースを使用するWebアプリ java-oauth-client http://client.example.com:8082/ としていたのですが、今回は、アクセストークン(やid_token)を取得するまでの記事にしているので、リソースサーバは省略、またOAuth Clientとしてcurlコマンドを使用します。従って、下記のようなシンプルな構成になります。
用途 サーバ名 URL 認可サーバ。ユーザIDごとの認可情報を管理するサーバ。 java-oauth-server http://localhost:8080/ リソースサーバ。ユーザIDごとのデータや機能をもったサーバ。 省略 - OAuth Client。リソースサーバのリソースを使用するアプリ。 今回はcurl - おおまかな流れ
おおまかな流れについても、基本的にいままでのAuthleteの使用方法と変わらず、
- Authleteへのサインアップ
- 認可サーバの登録・クライアントの登録
- 認可サーバの構築、リソースサーバの構築(省略)
- Webアプリケーションからの疎通(アクセストークン取るまで)
となるのですが、Authlete を使って CIBA 対応の認可サーバーを作る (中のヒトかな)の記事にあるように、アカウントのサインアップはAuthlete社の方に問い合わせる必要がありそうです。
したがって今回の記事では、アカウントのサインアップが済んでいて、CIBA対応のAuthleteのサイト(通常だと https://so.authlete.com/ だけどCIBA対応版は別URL )で下記の情報は取得済、という前提で話を進めます。
- そのアカウントにひもづく認可サーバの、API キー/API シークレット
API キー API シークレット 116xxxxxxxx sZUkxxxxxxxxxxxxxxxxxxx
- その認可サーバに登録されたOAuth Clientの クライアント ID/クライアントシークレット
クライアント ID クライアントシークレット 249xxxxxxx WUItxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ちなみに、認可サーバのAPI キー/API シークレット は、下記の サービス一覧 >> サービス詳細より 確認できます。
また、認可サーバに登録されたOAuth Clientの クライアント ID/クライアントシークレット は、クライアントアプリ開発者コンソール の、アプリ一覧 >> アプリ詳細より 確認できます。
環境設定
さて、AuthleteのWEBサイトでCIBAを使用可能にするための環境設定をいくつか。
認可サーバ側の設定
さきほどの、認可サーバ側の API キー/API シークレット を確認したサイト(サービス管理者コンソール)
にて「サービス一覧 >> サービス詳細 >> CIBA」タブに遷移し、
項目 値 サポートするトークンデリバリーモード POLL,PING,PUSH ユーザーコードのサポート サポートする を選択します。
OAuth Client側の設定
OAuth Clientの クライアント ID/クライアントシークレット を確認したサイト(クライアントアプリ開発者コンソール)にて「アプリ一覧 >> アプリ詳細」に遷移。
「基本情報」タブにて
項目 値 クライアントタイプ CONFIDENTIAL を選択します。
「認可」タブにて
項目 値 クライアント認証方式 CLIENT_SECRET_BASIC を選択します。
「CIBA」タブにて
項目 値 トークンデリバリーモード POLL ユーザーコードの要求 要求する を選択します。
以上で、POLLモードで動かすときの認可サーバ、OAuth Clientの環境設定は完了です。
動かしてみる
認可サーバを構築
まずは、認可サーバを構築します。GitHubのリポジトリをcloneしてきて、設定ファイル(authlete.properties)に API キー、API シークレット、base_urlを設定すればOKです。
$ git clone https://github.com/authlete/java-oauth-server.git $ cd java-oauth-server $ cat authlete.properties service.api_key = 116xxxxxxxx ← 正しい API キー に変更してください service.api_secret = sZUkxxxxxxxxxxxxxxxxxxx ← 正しい API シークレット に変更してください base_url = https://api.authlete.com ← CIBA 対応のURLに変更してください(値はAuthlete社さんに要問い合わせ)起動します。
$ mvn clean jetty:run -Dauthlete.ad.workspace=masatomix/testProject ← 引数は後ででてくるシミュレータで設定する値以上で、認可サーバの構築は完了です。
認証デバイスの準備
バックチャネル認証リクエストを受信した認可サーバは、認証デバイスに対して「許可してよい?」という通知を送りますが、cloneしてきた認可サーバのコードはデフォルトでAuthlete CIBA Simulator へ通知を送るようになっています。なのでシミュレータのセットアップをおこないます。
https://cibasim.authlete.com/ へアクセスし、さきほどの引数に設定した、
Namespace Project masatomix testProject を指定し「Create」をクリック。(下記画面キャプチャは作成した後のもので「Open」になってますが。。)
すると、Authentication Device(AD)のシミュレータ画面に遷移します。Authleteさん提供の認可サーバはダミーのユーザ認証がコーディングされていて、
User ID User Code 1001 675325 でログイン可能となっています。従って、キャプチャにあるとおり「1001」というUser IDを指定して「Launch AD simulator」をクリック。
シミュレータが待ち状態になりました。この画面でOAuthの認証/認可を行うので、画面は閉じずに出しておいてください(認可サーバがバックチャネル認証リクエストを受信したときにここにWebSocketでプッシュ通知がくるっぽい)。
ちなみに、この画面をスマホとかで開いておくと、わりと臨場感がでます。全然関係ないPC上のcurlから認証リクエストを送ると、スマホに通知が来るようなイメージです。
バックチャネル認証リクエストを送信
さてさっそく認可サーバへ、認証リクエストを送ってみます。
$ clientId=249xxxxxxx ← クライアント ID $ clientSecret=WUItxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ← クライアントシークレット $ curl http://localhost:8080/api/backchannel/authentication -X POST \ --user ${clientId}:${clientSecret} \ -d 'login_hint=1001' \ -d 'user_code=675325' \ -d 'scope=openid' { "auth_req_id": "Xe250q9AoSdUL_xohrPm8txYNUo8VlddhLv1ENUY6SM", "interval": 5, "expires_in": 600 } $auth_req_id (認証リクエストID)が得られました。後でつかうので記録しておいてください。
認証デバイスで、認証処理
認証リクエストを送信すると、さきのほどのシミュレータにOAuthでおなじみの認可画面が表示されていると思います。今回は「Allow」を選択。
トークンリクエストを送信
ユーザの認可が得られたので、さきほどの auth_req_id が使用可能になっています。トークンを取得する準備が出来ていますので、トークンリクエストを送信します。
$ clientId=249xxxxxxx ← クライアント ID $ clientSecret=WUItxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ← クライアントシークレット $ curl http://localhost:8080/api/token -X POST \ --user ${clientId}:${clientSecret} \ -H 'Content-type: application/x-www-form-urlencoded' \ -d 'auth_req_id=Xe250q9AoSdUL_xohrPm8txYNUo8VlddhLv1ENUY6SM' \ -d 'grant_type=urn:openid:params:grant-type:ciba' { "access_token":"ldofpBo8hO67CNr4sE_Cibt1FYZ8RpQCIPVlUaeokks", "refresh_token":"U0JyhKdXh-h3h6hDLiu3eart9RpEwnSClMtgGjAFu5o", "scope":"openid", "id_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdF9oYXNoIjoiRkxwdFBEaWlMbUcwdkVLWFZndjBUZyIsInN1YiI6IjEwMDEiLCJhdWQiOiIyNDkzOTMxNjU5OTciLCJhdXRoX3RpbWUiOjE1NTM4NTE3MjQsImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTUzOTM4MTM0LCJpYXQiOjE1NTM4NTE3MzR9.7G_VfqlSlDd0cOSjZaRorSrbcH3PoKneM_YalCpFHig","token_type":"Bearer","expires_in":86400 }アクセストークンが取得できましたね!今回はscopeを openid にしているのでid_tokenも得られています。
$ echo eyJhdF9oYXNoIjoiRkxwdFBEaWlMbUcwdkVLWFZndjBUZyIsInN1YiI6IjEwMDEiLCJhdWQiOiIyNDkzOTMxNjU5OTciLCJhdXRoX3RpbWUiOjE1NTM4NTE3MjQsImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTUzOTM4MTM0LCJpYXQiOjE1NTM4NTE3MzR9 | base64 -D | jq { "at_hash": "FLptPDiiLmG0vEKXVgv0Tg", "sub": "1001", "aud": "249393165997", "auth_time": 1553851724, "iss": "https://authlete.com", "exp": 1553938134, "iat": 1553851734 }実際はポーリングする
今回の処理は push,ping,poll のモードのうちpollでやっているので、認証リクエストがOKされたかどうかの通知は来ません。なので実際は、認証リクエストを送信してからアプリがポーリングする必要がありそうです。
たとえば下記のようなシェルを実行してみます。
$ cat ciba_request.sh #!/bin/bash clientId=249xxxxxxx ← クライアント ID clientSecret=WUItxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ← クライアントシークレット login_hint=1001 user_code=675325 backchannelReq=`cat << EOS curl http://localhost:8080/api/backchannel/authentication -X POST \ --user ${clientId}:${clientSecret} \ -d 'login_hint=${login_hint}' \ -d 'user_code=${user_code}' \ -d 'scope=openid' -s | jq .auth_req_id -r EOS ` auth_req_id=`eval "${backchannelReq}"` echo ${auth_req_id} for i in {0..3}; do sleep 3 tokenReq=`cat << EOS curl http://localhost:8080/api/token -X POST \ --user ${clientId}:${clientSecret} \ -H 'Content-type: application/x-www-form-urlencoded' \ -d 'auth_req_id=${auth_req_id}' \ -d 'grant_type=urn:openid:params:grant-type:ciba' -s EOS ` token=`eval "${tokenReq}"` error=`echo ${token} | jq 'select(.error_description==null)'` echo ${token} | jq if [ -n "$error" ]; then break; fi done$ ./ciba_request.sh lrHy0QdUalqpL7K2MRMfV_uhCLuvolCk5hS70LEb7R8 { "error_description": "[A200308] The end-user has not been authenticated yet.", "error": "authorization_pending", "error_uri": "https://www.authlete.com/documents/apis/result_codes#A200308" } { "error_description": "[A200308] The end-user has not been authenticated yet.", "error": "authorization_pending", "error_uri": "https://www.authlete.com/documents/apis/result_codes#A200308" } // ココでシミュレータでAllowを押下したら。。 { "access_token": "RexqI1mrrCpVI9fiYJWhxuJMSSOfD6j1ijNXs-cXOts", "refresh_token": "x0CuGD-CPK1q2b8WzuU5WYBeCoIxdkBg5aaenLCeeWQ", "scope": "openid", "id_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdF9oYXNoIjoidVBRWVVnT1BmenVaQ1Jab0E1b21XUSIsInN1YiI6IjEwMDEiLCJhdWQiOiIyNDkzOTMxNjU5OTciLCJhdXRoX3RpbWUiOjE1NTQyNTc4NzksImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTU0MzQ0MjgxLCJpYXQiOjE1NTQyNTc4ODF9.1mdVZ2hub3GzwGNNxaL1HxlQHdIioSvLyp0UJfdMDog", "token_type": "Bearer", "expires_in": 86400 } $よさそうですね。。
まとめ
今回はAuthleteサービスを用いて、CIBA対応の認可サーバ(pollモード)を構築してみました。
まだまださわりを構築しただけで、全体感の理解とはほぼ遠いのですが、Authleteを用いることで容易に認可サーバを立ち上げることが出来ました。おつかれさまでした。
関連リンク
- OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 draft-02
- 【2019年版】世界最先端の認証認可技術、実装者による『CIBA』解説
- Authlete を使って CIBA 対応の認可サーバーを作る
- FAPI (Financial-grade API) and CIBA (Client Initiated Backchannel Authentication)
- 認可サービス Authlete、オープン API の適用シーンを広げる新仕様「CIBA」に対応
- Authlete CIBA Simulator
- Authleteを使った認可サーバの構築と、OAuthクライアント(Webアプリケーション)からの疎通
- OIDC Client Initiated Backchannel Authentication Flow (CIBA)とは - 概要編
登壇されていた方が この処理シーケンスのことをOAuth Dance と説明されてたのが印象的 :-) ↩
- 投稿日:2019-04-03T10:12:17+09:00
Java でコールバック簡単なサンプルPart2 無名クラスの例
public interface myCallback { void onSuccess(); void onError(String err); } public class App { public static void main(String[] args) { // call your method 無名クラス利用 doSomething("list your Params", new myCallback(){ @Override public void onSuccess() { // no errors System.out.println("Done"); } @Override public void onError(String err) { // error happen System.out.println(err); } }); } private void doSomething(String param, // some params.. myCallback callback) { // now call onSuccess whenever you want if results are ready if(results_success) callback.onSuccess(); else callback.onError(someError); } }
- 投稿日:2019-04-03T09:49:15+09:00
Stanford NER Taggerを自分のデータで訓練
NERとは、Named Entity Recognitionの略で、固有表現認識という自然言語処理のタスクの一つです。Stanford NER Taggerは、このタスクを解くためのツールです。今回は、これを自分で訓練します。
事前準備
まず、訓練データの例をダウンロードします。
https://github.com/synalp/NER/blob/master/corpus/CoNLL-2003/eng.train次に、Stanford NER Taggerをダウンロードします。
https://nlp.stanford.edu/software/CRF-NER.shtml#Downloadそして、jdkをインストールします。
apt install default-jdk訓練データの準備
ダウンロードしたeng.trainを整形します。
out = [] with open("eng.train", "r") as f: for line in f: line = line.split() if len(line) > 2: out.append(str(line[0])+"\t"+str(line[-1]).replace("I-","").replace("B-","")+"\n") else: out.append("\n") with open("train.tsv") as f: f.write(''.join(out))訓練
訓練準備
- stanford ner taggerをunzipして、展開後のディレクトリに入ってください。
- そのディレクトリ内に、train.tsvを入れてください。
プロパティファイルの作成
train.proptrainFile = train.tsv serializeTo = ner-model.ser.gz map = word=0,answer=1 useClassFeature=true useWord=true useNGrams=true noMidNGrams=true maxNGramLeng=6 usePrev=true useNext=true useSequences=true usePrevSequences=true maxLeft=1 useTypeSeqs=true useTypeSeqs2=true useTypeySequences=true wordShape=chris2useLC useDisjunctive=trueこれを、train.propというファイル名で保存してください。
訓練の実行
java -cp stanford-ner.jar edu.stanford.nlp.ie.crf.CRFClassifier -prop train.propすると、ner-model.ser.gzという名のファイルとしてモデルが出来上がります。
モデルをpythonから使う
nltkのStanford NER Taggerのラッパーを使えば、モデルをpythonから使えます。
import nltk from nltk.tag.stanford import StanfordNERTagger sent = "Balack Obama kills people by AK47" model = "./ner-model.ser.gz" jar = "./stanford-ner.jar" tagger = StanfordNERTagger(model, jar, encoding='utf-8') print(tagger.tag(sent.split()))[出力]
[('Balack', 'PER'), ('Obama', 'PER'), ('kills', 'O'), ('people', 'O'), ('by', 'O'), ('AK47', 'O')]参考
[0] https://nlp.stanford.edu/software/crf-faq.html#a
[1] https://blog.sicara.com/train-ner-model-with-nltk-stanford-tagger-english-french-german-6d90573a9486
- 投稿日:2019-04-03T08:59:28+09:00
ScalaのTry的なやつをJavaでやりたい!!
はじめに
ScalaのTry関数とは,例外ベースのAPIをOptionベースのAPIに変換するための汎用関数です.この記事では,Javaで例外ベースのAPIをOptionalベースのAPIに変換する方法について述べます.
この記事の対象読者は次のような人です.
- Scalaを習得している人
- Javaに馴染みがない人
例外ベースのAPIをOptionalベースのAPIに変換する方法
メソッドの中ででtry-catchを隠蔽し,クライアントに対してOptionalベースのインタフェースを提供します.
// 時間をWebAPIから取得するメソッド public static Optional<String> getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); ...... ...... return Optional.of(time.toString()); } catch (IOException e) { e.printStackTrace(); } return Optional.empty(); }サンプルプログラム
現在時刻をWebAPIから取得し,表示するプログラムを次の2通りの方法で実装しました.
- 例外ベース
- Optionalベース
例外ベースのプログラム
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class Main { public static void main(String[] args) { System.out.println(getTime()); } // 時間をWebAPIから取得するメソッド private static String getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("GET"); http.connect(); // 接続先から文字列を読み込む. BufferedReader reader = new BufferedReader(new InputStreamReader(http.getInputStream())); StringBuilder time = new StringBuilder(); String line = ""; while((line = reader.readLine()) != null) time.append(line); reader.close(); return time.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } }Optionalベースのプログラム
getTime()メソッドがOptional型を返すように書き換えました.メインルーチン(mainメソッド)からすると,getTime()メソッドはOptionalベースのインタフェースに見えます.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Optional; public class Main { public static void main(String[] args) { System.out.println(getTime().orElse("")); } // 時間をWebAPIから取得するメソッド private static Optional<String> getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("GET"); http.connect(); // 接続先から文字列を読み込む. BufferedReader reader = new BufferedReader(new InputStreamReader(http.getInputStream())); StringBuilder time = new StringBuilder(); String line = ""; while((line = reader.readLine()) != null) time.append(line); reader.close(); return Optional.of(time.toString()); } catch (IOException e) { e.printStackTrace(); } return Optional.empty(); } }おわりに
もっとスマートなやり方あったら,コメントお願いします.
- 投稿日:2019-04-03T08:59:28+09:00
Javaのtry-catchをOptionalで書き直す
はじめに
例外処理を行う際,try-catch構文が利用可能ですが,scala.util.Tryを利用すると関数型っぽい実装をすることができます.
Javaでは,Tryクラスは利用できませんが,例外内容に関心がない場合,Optionalクラスを利用することが可能です.そこで,この記事では,Javaで例外ベースのAPIをOptionalベースのAPIに変換する方法について述べます.
この記事の対象読者は次のような人です.
- Scalaを習得している人
- Javaに馴染みがない人
例外ベースのAPIをOptionalベースのAPIに変換する方法
メソッドの中ででtry-catchを隠蔽し,クライアントに対してOptionalベースのインタフェースを提供します.
// 時間をWebAPIから取得するメソッド public static Optional<String> getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); ...... ...... return Optional.of(time.toString()); } catch (IOException e) { e.printStackTrace(); } return Optional.empty(); }サンプルプログラム
現在時刻をWebAPIから取得し,表示するプログラムを次の2通りの方法で実装しました.
- 例外ベース
- Optionalベース
例外ベースのプログラム
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class Main { public static void main(String[] args) { System.out.println(getTime()); } // 時間をWebAPIから取得するメソッド private static String getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("GET"); http.connect(); // 接続先から文字列を読み込む. BufferedReader reader = new BufferedReader(new InputStreamReader(http.getInputStream())); StringBuilder time = new StringBuilder(); String line = ""; while((line = reader.readLine()) != null) time.append(line); return time.toString(); } catch (IOException e) { e.printStackTrace(); } finally { reader.close(); } return ""; } }Optionalベースのプログラム
getTime()メソッドがOptional型を返すように書き換えました.メインルーチン(mainメソッド)からすると,getTime()メソッドはOptionalベースのインタフェースに見えます.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Optional; public class Main { public static void main(String[] args) { System.out.println(getTime().orElse("")); } // 時間をWebAPIから取得するメソッド private static Optional<String> getTime() { try { // 接続先URLや接続方法を設定する. URL url = new URL("http://api.aoikujira.com/time/get.php"); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestMethod("GET"); http.connect(); // 接続先から文字列を読み込む. BufferedReader reader = new BufferedReader(new InputStreamReader(http.getInputStream())); StringBuilder time = new StringBuilder(); String line = ""; while((line = reader.readLine()) != null) time.append(line); reader.close(); return Optional.of(time.toString()); } catch (IOException e) { e.printStackTrace(); } finally { reader.close(); } return Optional.empty(); } }おわりに
もっとスマートなやり方あったら,コメントお願いします.