サクッとBCryptで文字列を暗号化する
コマンドライン引数で文字列をBCryptで暗号化するコード書いたのでメモしておく。
Mavenなどのパッケージ管理ツール使わず、とにかくサクッとやる想定。
パッケージダウンロード
利用するライブラリをサイトから手動ダウンロードする。
spring-security-coreだけだと実行時にcommons-loggingがないというjava.lang.NoClassDefFoundErrorが出力されるので、とりあえず追加。
実装
これらのライブラリをlib配下に格納し、以下の2クラスを実装する。
引数をBCryptで暗号化するCLBCryptPasswordEncoder.java。
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.apache.commons.logging.LogFactory; public class CLBCryptPasswordEncoder{ public static void main(String args[]){ String textPassword = args[0]; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); System.out.println(encoder.encode(textPassword)); } }
平文パスワードと暗号化済パスワードが一致するか確認するCLBCryptPasswordMatcher.java。
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.apache.commons.logging.LogFactory; public class CLBCryptPasswordMatcher{ public static void main(String args[]){ BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String textPassword = args[0]; String encryptedPassword = args[1]; if (encoder.matches(textPassword, encryptedPassword)) { System.out.println("matched"); } else { System.out.println("mismatched"); } } }
ディレクトリ構成
ディレクトリ構造は以下のとおり。
- CLBCryptPasswordEncoder.java
- CLBCryptPasswordMatcher.java
- lib/
- commons-logging-1.2.jar
- spring-security-core-5.0.2.RELEASE.jar
コンパイル
$ javac -cp "lib/*" CLBCryptPasswordEncoder.java $ javac -cp "lib/*" CLBCryptPasswordMatcher.java
カレントディレクトリにクラスが生成される。
実行
暗号化と検証の実行。classpathにカレントディレクトリを追加。
$ java -cp "lib/*:." CLBCryptPasswordEncoder sonomirai $2a$10$ALcXPgrpOQKXoIyrgS90huCbgR906LtWrH1dOsZmHtBZdSB19n9Bi $ java -cp "lib/*:." CLBCryptPasswordMatcher sonomirai '$2a$10$ALcXPgrpOQKXoIyrgS90huCbgR906LtWrH1dOsZmHtBZdSB19n9Bi' matched $ java -cp "lib/*:." CLBCryptPasswordMatcher dummypswd '$2a$10$ALcXPgrpOQKXoIyrgS90huCbgR906LtWrH1dOsZmHtBZdSB19n9Bi' mismatched
こんな感じでやりたかったことはやれた。
Java本格入門13章をdocker上で写経する
はじめに
Java本格入門の13章「周辺ツールで品質を上げる」を写経した。
Maven使った操作はdocker上で写経したので、その時の手順を記録しておく。
誰かの役に立てば幸い。なお写経したコードはこのリポジトリにある。
準備
HTML形式のレポートを見るため、centos/httpdイメージからコンテナを起動する。
コンテナ起動
$ docker run --name javabook -h javabook -d -p 8080:80 centos/httpd
http状態確認
ブラウザでhttp://localhost:8080にアクセスして「It works!」と表示されることを確認する。
コンテナ内に入る
$ docker exec -it javabook /bin/bash
パッケージインストール
[root@javabook /]# yum install -y vim git java maven
Java&mavenバージョン確認
[root@javabook /]# java -version openjdk version "1.8.0_151" OpenJDK Runtime Environment (build 1.8.0_151-b12) OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode) [root@javabook /]# mvn -version Apache Maven 3.0.5 (Red Hat 3.0.5-17) Maven home: /usr/share/maven Java version: 1.8.0_151, vendor: Oracle Corporation Java home: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.151-1.b12.el7_4.x86_64/jre Default locale: en_US, platform encoding: ANSI_X3.4-1968 OS name: "linux", version: "4.9.49-moby", arch: "amd64", family: "unix"
Git準備
[root@javabook /]# git config --global user.email <メールアドレス> [root@javabook /]# git config --global user.name <ユーザ名> [root@javabook /]# git clone https://github.com/acroquest/javabook-maven-example.git Cloning into 'javabook-maven-example'... remote: Counting objects: 42, done. remote: Total 42 (delta 0), reused 0 (delta 0), pack-reused 42 Unpacking objects: 100% (42/42), done. [root@javabook /]# cd javabook-maven-example/
これで準備終わり。書籍の内容に入る。(書籍にはEclipseの手順とMavenの手順の両方が
掲載されているが、この記事ではMavenの手順のみ記載するので、章番号はとびとび。)
13-1-2 Mavenの基本的な利用方法
[root@javabook javabook-maven-example]# mvn package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building javabook-maven-example 1.0-SNAPSHOT [INFO] --------------------------------------------------- 〜中略〜 ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.java.book.app.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.191 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 〜中略〜 [INFO] Building jar: /javabook-maven-example/target/javabook-maven-example-1.0-SNAPSHOT.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1:13.426s [INFO] Finished at: Tue Nov 28 14:13:10 UTC 2017 [INFO] Final Memory: 18M/157M [INFO] ------------------------------------------------------------------------
man packageを実行するとビルドが始まって、問題なければBUILD SUCCESSが表示される。
ログを見ていて、とくに設定した覚えはないのにテストが実行されていることに気づいた。
そこでちょっと検証してみたところ、pom.xmlのdependencyにJUnitの記載があるかつsrc/test配下にテストファイルがあると、mvn packageでテストが実行されるように見えた。
pluginではJUnitを指定しておらず、dependencyを指定しただけなのに、テストが実行されて驚いたが、そんなものなんだろうか。
mvn installを実行するとローカルリポジトリにビルド成果物が登録される。ログには以下の通り出力される。
[INFO] Installing /javabook-maven-example/target/javabook-maven-example-1.0-SNAPSHOT.jar to /root/.m2/repository/com/java/book/app/javabook-maven-example/1.0-SNAPSHOT/javabook-maven-example-1.0-SNAPSHOT.jar [INFO] Installing /javabook-maven-example/pom.xml to /root/.m2/repository/com/java/book/app/javabook-maven-example/1.0-SNAPSHOT/javabook-maven-example-1.0-SNAPSHOT.pom
13-2-4 APIドキュメントを作成する
APIドキュメント確認
pom.xmlにmaven-javadoc-pluginの設定を記述してmvn siteを実行する。
生成されたHTMLをhttpdのドキュメントルートに配置する。
[root@javabook javabook-maven-example]# cp -rp target/site/apidocs/* /var/www/html/ [root@javabook javabook-maven-example]#
ブラウザでhttp://localhost:8080にアクセスしてAPIドキュメントを確認する。
13-3-3 Mavenによるフォーマットチェック
pom.xmlにmaven-checkstype-pluginの設定を記述してmvn clean package siteを実行する。
生成されたHTMLをhttpdのドキュメントルートに配置する。
[root@javabook javabook-maven-example]# rm -rf /var/www/html/* [root@javabook javabook-maven-example]# cp -rp target/site/* /var/www/html [root@javabook javabook-maven-example]#
ブラウザでhttp://localhost:8080にアクセスする。
Project ReportsのCheckstyleをクリックしてレポートを見る。けっこうErrorがある。。。
とりあえずErrorを0にするよう修正したが、あまり意味のある変更とは思えなかった。
Checkstyleの使い方は今度の課題かな。。。
13-4-4 Mavenによるバグチェック
pom.xmlにfixbugs-maven-pluginの設定を記述してmvn clean package siteを実行する。
生成されたHTMLをhttpdのドキュメントルートに配置する。
[root@javabook javabook-maven-example]# rm -rf /var/www/html/* [root@javabook javabook-maven-example]# cp -rp target/site/* /var/www/html [root@javabook javabook-maven-example]#
ブラウザでhttp://localhost:8080にアクセスし、FindBugsのレポートを見る。
13-5-3 テストを実行する
書籍だとEclipseで実行しているところを、Mavenで実行してみる。
先ほどまでのリポジトリ内に、書籍に掲載されているテスト用プログラム(わざとバグを入れてある)とテストコードを作成する。
mvn clean package siteを実行するとテストがコケてビルドに失敗する。
日本語が正しく出力できていない。。。そこは今後の課題。。。
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.java.book.app.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.101 sec Running acroquest.java.junit.GreetingTest Tests run: 3, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.019 sec <<< FAILURE! Results : Failed tests: getMessage_\u591C\u958B\u59CB(acroquest.java.junit.GreetingTest): getMessage_\u663C\u958B\u59CB(acroquest.java.junit.GreetingTest): Tests run: 4, Failures: 2, Errors: 0, Skipped: 0
コード修正して再実行するとテストに成功する。
JUnitの結果もCheckstyle, FindBugsと同様にレポート出力されるかと思ったが、されなかった。
実際はJUnitの結果はJenkinsで出力させることになるので、気にせず次に進む。
次の章に向けて、Gitのローカルリポジトリをリモートリポジトリにコミットしておく。
13-6-2 Jenkinsの環境を準備する
書籍だとWindowsにJenkinsをインストールしているところを、DockerのJenkinsコンテナを立ち上げて利用する。
Jenkinsコンテナ準備
Jenkinsコンテナを立ち上げて、Mavenをインストールする。
$ docker run --name javabook_jenkins -h javabook -u 0 -d -p 8081:8080 -p 50000:50000 jenkins $ docker exec -it javabook_jenkins /bin/bash root@javabook:/# apt-get update; apt-get install -y maven
Jenkins状態確認
ブラウザでhttp://localhost:8081にアクセスして以下の画面が表示されることを確認する。
Jenkins設定作業
書籍に掲載された方法で設定していく。(「Create First Admin User」画面は、どうもユーザが
作成できなかったので、「Continue as admin」を選択して先に進んだ。)
13-6-3 Jenkinsでビルドを実行する
書籍の手順通り設定する。ソースコードの取得元の設定では、先ほどコミットしたリモートリポジトリを設定する。
とくに問題なくビルド成功するはず。
13-6-4 Jenkinsでレポートを作成する
書籍の手順通り設定すると、Checkstyle, FindBugs, JUnit, カバレッジのレポートが出力される。
おお、こんな感じの画面を見てみたかった。よかった。
JUnitの結果もこんな感じで表示される。
さいごに
Java本格入門の13章「周辺ツールで品質を上げる」をdocker環境で写経する手順について書いた。
JavaアプリってWindows上のEclipseで開発してLinuxで動作させることが結構あると思うが、
これまで環境ごとの周辺ツールの使い方やツール同士の連携のさせ方がわかっていなかった。
13章を写経することで、その辺りの使い方がはっきり理解できてよかった。
ゼロから作るDeep Learning 5.7.2項のTwoLayerNetを理解するために書いた図
ゼロから作るDeep Learning 5.7.2項のTwoLayerNetの処理が、初見では理解できなかった。
そこで書籍の内容を復習して図示してからTwoLayerNetを読んだところ、かなり理解が進んだので、その時書いた図を残しておく。
TwoLayerNet理解ためには、ReLU、Sigmoid、Softmaxは各層の活性化関数で、Affineは層の間の重み(重みは行列で表される)の内積ということがイメージできている必要があると思うが、自分は最初そこがイメージできていなくて苦戦したので、そこをサポートするような図を描いたつもり。
Selenium3をMacで動かす
Selenium使うことになったので、Selenium実践入門読みながらインストールしようと思ったら、Seleniumのバージョンが3に上がってて、パッケージ構成から違ってて涙目になった。
ググったところ、下記の記事が参考になったが、一部つまづくところがあったので、自分のためにメモを残す。
なお対象のブラウザはFirefoxとChrome。
Selenium入門その6[Selenium3でWebDriver(Java/Junit4)の環境を作成しEdge,Chrome,Firefoxで確認してみる]
環境情報
ソフト | バージョン |
---|---|
Mac | OS X El Capitan 10.11.6 |
Selenium | 3.4.0 |
mozilla Firefox | 54.0.1 |
geckodriver | 0.18.0 |
Google Chrome | 59.0.3071.115 |
chromedriver | 2.30 |
前提
- Eclipseがインストール済みであること
- Firefoxがインストール済みであること
- Chromeがインストール済みであること FirefoxとChromeがインストール済みであることの確認は、LaunchpadでFirefox, Chromeで検索して、プログラムが見えればOKだと思う。
環境構築
基本は参考ページ通りでいいが、chromedriverはPATHの通ったディレクトリに配置しておかないと、実行時にエラーになるっぽい。
自分は/usr/local/bin配下に配置した。
実行
参考ページのソースを以下のように微修正して実行した。
package sample.selenium3; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.remote.DesiredCapabilities; public class Selenium3Sample { @Test public void firefoxTest() { System.setProperty("webdriver.gecko.driver", "./exe/geckodriver"); DesiredCapabilities cap = DesiredCapabilities.firefox(); cap.setCapability("marionette", true); WebDriver driver = new FirefoxDriver(cap); driver.navigate().to("http://www.google.com"); driver.findElement(By.id("lst-ib")).sendKeys("Selenium3"); driver.findElement(By.name("btnK")).click(); if(driver!=null) { driver.close(); } } @Test public void chromeTest() { System.setProperty("webdriver.chromedriver.driver", ""); //chromedriverはPATHの通っている/usr/local/binに配置 WebDriver driver = new ChromeDriver(); driver.navigate().to("http://www.google.com"); driver.findElement(By.id("lst-ib")).sendKeys("Selenium3"); // driver.findElement(By.name("btnK")).click(); //動かなかった driver.findElement(By.id("lst-ib")).sendKeys(Keys.ENTER); //動いた if(driver!=null) { driver.close(); } } }
参考ページからの変更点は3点。
- DesiredCapabilities周りの設定の削除
なしでも動いたので削除した。Seleniumのバージョンが上がって、なしで動くようになった? - chromedriverのPATH指定
exe配下にchromedriver置いてもちゃんと読んでもらえず、エラーになってしまう。
PATHの通ったところにchromedriverを配置したら読んでもらえたので、setPropertyの第二引数は明示的に空にしておいた。 - chromedriverでの検索実行
「driver.findElement(By.name(“btnK”)).click();」だと動かなかったので、とりあえず「driver.findElement(By.id(“lst-ib”)).sendKeys(Keys.ENTER);」にした。
まとめ
STSをMacにインストールして日本語化する
同じような手順がネットに載っているのは重々承知しているが、
その通りやっても動かなかったので、成功した手順をメモで残す。
バージョン情報
Mac: OS X El Capitan 10.11.6
STS: 3.8.4
pleiades:1.7.27
手順
- STSをサイトからダウンロードする
- 解凍する
tar -zxvf spring-tool-suite-3.8.4.RELEASE-e4.6.3-macosx-cocoa-x86_64.tar.gz
- sts-bundleディレクトリ配下のSTSをダブルクリックして起動する。
日本語化前に一度STSを起動するこの手順を抜かすと、日本語化した後STSが起動しない気がするので、やっておく。
ワークスペースを開いてIDEの画面が見えるところまで確認したら閉じる。 - pleiadesをサイトからダウンロードする。
「Pleiades All in One」ではなく、最新版ダウンロードからダウンロードすることに注意。 - 解凍する
unzip pleiades.zip -d pleiades
- pleiadesディレクトリ内のfeaturesとpluginsをコピーする。ここはGUIの想定で説明する。
手順2で作成されたsts-bundleディレクトリ内のSTSファイルを右クリックして「パッケージの内容を表示」をクリックする。
Contents/Eclipse配下にfeaturesとpluginsディレクトリがあるので、pleiades内の同名のディレクトリ配下のファイル「jp.sourceforge.mergedoc.pleiades」をコピーする。 - Contents/Eclipse配下のSTS.iniのバックアップを念のため取っておく。
cp STS.ini STS.ini.org
- STS.iniの末尾にオプションを追記する。
echo '-javaagent:../Eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar' >> STS.ini
- sts-bundleディレクトリ配下のSTSをダブルクリックして起動する。
自分はこの手順で動いた。サンプルのプロジェクトを用いた動作確認はこちらの手順で実施した。
ゼロから作るDeep Learning 4.4節を理解するために考えたことのメモ
ゼロから作るDeep Learning 4.4節がよくわからなくて、3章から読み直したらなんとなくわかった気になったので、自分なりの理解をメモをとして残しておく。
まずわからなかったのが、以下の文章。
形状が2×3の重みWだけを持つニューラルネットワーク
最初はこの文章だけでは、どんなニューラルネットワークをイメージすればいいのか分からなかったが、図3-14と図3-16を踏まえると、入力層が2個, 出力層が3個, 隠れ層なしの1層ニューラルネットワーク(バイアスと活性化関数は省略)を意味していることがわかった。
そのあと、simpleNetを使ってみるところでまたつまづいたが、出てきている値を上図に当てはめるとイメージが湧いた。ガウス分布で重み決めて、適当な入力与えて、結果的に最大だったインデックスを正解ラベルにしているということだと思う。 普通は正解ラベルは決まっているものだが、4.4節はあくまでニューラルネットワークに必要な勾配の概念を学習するという章なので、勾配の説明のために、普通とは違うことをしているのだと思う。その後の4.5節では、MNISTデータセット使って、実際の学習に即したやり方をしている。
そのあと勾配を求めていて、dWの値を見ると、正解ラベルへの重みはマイナス、正解ラベル以外への重みはプラスになっていることがわかる。これはつまり正解ラベルの重みを大きく、それ以外の重みを小さくするよう学習を進めようとしていることがわかる。
インデックス2と値の近いインデックス0への重みdw11, dw21は値が大きいのは、「dw11, dw21の重みを今以上に大きくしたら、正解であるインデックス2との区別がつかなくなるからやめろよ!」という意味だと思う。 (こんな風に入力と重みの関係が密なのは、今学習データが1つだけだからで、2つ以上になったらこの辺りは隠れてしまう気がする。)
今回は入力が(0.6, 0.9)の1個のみだが、他の入力が来た時でも、正解を正解と判断できるように重みを更新しているということだと思う。
リンク集作成アプリ「localportal」の紹介
この投稿は「作ったアプリ自慢! Advent Calendar 2016」の23日目の記事です。
はじめに
紹介するのは、手軽に,検索しやすい形でリンクを登録できるアプリ「localportal」です。
「localportal」という名前は「HTML5のlocalstorageを使っている」+「個人用portalの役割を担っている」というところから名付けました。
まだまだプロトタイプレベルですが、最低限の機能は実装したつもりで、個人では職場で使い始めています。
利用技術
Ver0.0.5時点の利用技術は次の通りです。
- bootstrap v3.3.7
- AngularJS v1.5.9
- ngStorage v0.3.10
- cmEditableText
AngularJS2がリリースされていますが、将来的に 別のAngular1のアプリをメンテする可能性があるので、勉強のためあえてAngularJS1を使いました。
機能の紹介
使用中の画面を見てもらうのがはやいと思うので、メインの機能である「リンクの登録」、「タグ検索」、「タグ追加」をGIF画像で紹介します。(画像はVer0.0.4時点)
【デモ1】リンクの登録
localportalは、ブラウザからリンクを登録することができます。
デモ1では、AngularJS公式サイトのAPIドキュメントページをリンクとして登録しています。
その際、登録名は「Angular APIドキュメント」、タグは「angularjs,api,docs」で登録しています。
今回のリンクは公式サイトなので、「official」のタグがあった方が後で検索しやすいですが、ここでは設定しておりません。この後のデモ3で設定します。
【デモ2】タグ検索
localportalは、タグを指定してリンクを絞り込むことができます。
デモ2では、リンクを「angularjs」、「event」、「doorkeeper」と絞り込み、Doorkeeperの「Angular Japan User Group」のページを開いています。
【デモ3】タグ追加
localportalは、登録済みリンクのタグを更新することができます。
デモ3では、「リンクの登録」で登録したAngularJS公式サイトのAPIドキュメントページを「official」というタグで絞り込もうとしたところ、「official」がタグとして設定されておらず検索できなかったことから、登録済みのリンクに対して「official」のタグを追加してから検索をし直すというシナリオを実行しています。
その他の機能はREADMEの「Usage」をご覧ください。
開発の動機
デモではWebサイト(URL表記のリンク)を登録・検索していたのですが、localportalを開発した一番の動機は、ファイルサーバのパス(UNC表記のリンク)を手軽に,検索しやすい形で登録できるアプリが欲しかったからです。
なぜURL表記のリンクではなくUNC表記のリンクかというと、仕事では日々メールやIRCでたくさんのファイルサーバのパスが送られてくるのに、この管理を効率化する仕組みがないと思ったからです。(一方のURL表記のリンクについては、会社自体がポータルサイトを持っていたり、ブラウザが頻繁に使うサイトを覚えておいてくれたりするので、UNC表記のリンクに比べるとアクセスの効率化はできていることが多いと思っています。)
ここから、「従来のファイルサーバのパスの管理方法と問題」と「localportalでの解決策」を紹介します。
従来のファイルサーバのパスの管理方法と問題
従来のファイルサーバのパスの管理方法は、次の3通りに分類できると思っています。
- ショートカット格納用フォルダを作って、そこでショートカットを階層構造で管理する
- テキストもしくはHTMLで簡単なリンク集を作成して管理する
- 浅い階層だけショートカットで管理していて、メールに記載のパスを開くときはメールクライアントの検索機能やGoogle Desktopの機能で検索する
1, 2の管理方法だと、リンクを階層構造で管理するので、階層構造を綺麗に保つための管理コストがかかるという点が問題となり、3の管理方法だと、メール全体が検索範囲になるので、ノイズが入ってしまって検索効率が悪いという点が問題になります。
localportalでの解決策
localportalは、タグ付け機能により、従来のファイルサーバのパスの管理方法の問題を解決しています。(しているつもりです。)
従来の問題 | localportalでの解決策 |
---|---|
階層構造で管理すると管理コストがかかる | タグ機能により階層構造なしで効率的な管理ができる |
メール検索だと検索範囲が広いのでノイズが入って検索効率が悪い | 検索範囲をタグに限定しているので検索効率が高い |
タグ付け機能自体は、最近のWebサービスだとよくある機能だと思うのですが、この機能をlocalstorageと組み合わせて、ブラウザ上でリンクの管理が完結するSPAという形にまとめてあるところは、このアプリのユニークなところかなと思っています。
おわりに
現状の実装はプロトタイプレベルで、まだまだ改善の余地がありますが、利用技術に挙げた技術や先人のノウハウのおかげで、自分が欲しいと思っていたアプリを作ることができてよかったです。
今後は利用技術の深堀やテストの仕方を学んで、アプリのユーザビリティを高めていきたいと思っています。
それでは、よいお年を。