2015年8月5日水曜日

Google の 2 段階認証を有効にしてみた

概要

2段階認証とはログイン時にID/PWだけでなく、登録した携帯電話に送られてくる確認用のコードを入力して初めてログインしたことにできる機能です
Googleの2段階認証を有効にしたところいろいろとややこしい自体になったので状況をメモしておきます
2段階認証を有効にする方法はここでは紹介しません

環境

  • Google 2段階認証 2015/08/05 時点での機能
  • 有効にしたGoogleアカウントは1つ
  • Google アカウントを利用しているデバイスは全部で7台 (Windows x 2, Mac x 2, iPhone, Android x 2)

遭遇したケース

とりあえず全てがログアウト状態になる

Gmail, GoogleDrive, その他Google認証を使っているアプリ等すべてのアプリがログアウト状態になりました
かつアプリをインストールしている全マシンでログアウト状態になります
かつ各マシンでアプリにログインするたびに携帯に確認コードが飛んできます

SMTP 認証が使えなくなった

Jenkinsのビルド失敗時のメールサーバをGoogleのSMTPサーバを使っていたのですがこれも2段階認証の対象になるようです
2段階認証を有効にすると、そんなケースのために「アプリ用のパスワード」というものを発行できるようになります
Googleアカウントの管理画面からアプリ用のパスワードは発行できます
ここを参考にするといいと思います
アプリ用のパスワードを発行したら、そのパスワードを認証用のパスワードとして使うことで2段階認証が発生せずJenkinsから認証できるようになります
また、アプリ用のパスワードは基本使い捨てなので忘れたら再度発行して入力しましょう
アプリ用パスワードの使い回しはやめたほうがいいです

iPhoneの連絡先の連携ができなくなった

これは上記の理由と同じで「アプリ用のパスワード」を発行して、そのパスワードでiPhoneから認証すればOKです

iPhone上のGoogle系のアプリについて

iPhone上でログアウトになっていたアプリは先ほどの連絡先連携の他に

  • Gmail
  • Google Chrome
  • Google Drive
  • Youtube

でした、これらの認証ですが、Google Chrome だけ 2 段階認証を一回実施したら他のアプリはすでにログイン状態になっていました
理由はよくわからないですが、iPhone上で一度 2 段階認証を実施すると他のアプリの認証もOKになったりするんでしょうか
自分は iPhone 上にインストールしている Google系のアプリはそれだけだったのですが、他のアプリもインストールしている人はもしかしたら別途 2 段階認証 or アプリ用パスワードの発行が必要になるかもしれません

Android上のGoogle系のアプリについて

基本的にはiPhoneと同じです
アプリそれぞれで 2 段階認証してください
Androidの場合は、設定に「アカウントと同期」できる端末もありここで Google アカウントを認証すれば全アプリに認証が適用されるので楽です

Tips

  • 携帯(メールアドレス)が変わる場合は 2 段階認証をOFFにしてから携帯を変更したほうがよさそう
    そうしないと 2 段階認証用のコードを受け取れなくなってしまいログインできなくなるためです
    そんなときを想定しているのか、バックアップコードというものが発行できるようです
    バックアップコードには 10 個の確認コードが含まれており、それぞれ一回しか使えないですが、携帯に送られてくる確認コードと同様に使用することができます
    バックアップコードは印刷して保存しておくことを薦めていました

最後に

とにかく面倒くさいです
それだけセキュアになったと思えば良いといえば良いかなと
まぁ 2 段階認証を設定していても結局 PC とか盗まれて PC にパスワードを設定していなかったらほぼ終わりなんですけどね
それでも Google アカウントを Webのアイデンティティのメインにしているのであれば絶対設定したほうがいいと思います

2015年8月3日月曜日

現在サービスが実行されていないため、Windows Update で更新プログラムを確認できません

ネットでいろいろ調べてドライバが変だったり変なアプリが入っているから
みたいな記事をみたけど全部ハズレ
自分は以下で解決しました

WindodwsUpdateの自動更新をOFFにして手動で更新を行う

ポイントは自動更新をOFFにすること
理由は全然わからんないけど、これで無事WindowsUpdateできました
1年ぶりくらいに起動したWindowsだったので、長期間起動していないケースの方はお試しあれ

ちなみに 2014/06/30 から 2015/08/03 までの1年ちょっとの更新で

更新プログラム数は約 170
更新 -> 再起動の作業を 7 回
更新完了までの時間は約 4:00 ほど

かかりました
面倒くさすぎる

2015年7月29日水曜日

Java の Mockito を使ってみた

概要

mockito はJUnit等のユニットテストで使用する Mock オブジェクトを作成するためのライブラリです
例えば外部サービスと接続するアプリでローカルでテストする場合は接続しないでテストしたかったりするケースなんかに使えます

環境

  • Mac OX X 10.10.4
  • Eclipse Luna 4.4
  • Java 1.8.0_31
  • Maven 3.2.1
  • Mockito 1.10.19

使ってみる

サンプルプロジェクトの作成

EclipseでMavenプロジェクトを作成します
maven-archetype-quickstartを ArtifactId に選択してプロジェクトを作成しました
本記事中で扱うパッケージは「com.sample.test」としています

Mockito を使ったテストを書いてみる

maven-archetype-quickstartでプロジェクトを作成すれば「src/main/java/com.sample.test.AppTest.java」があると思うのでそれを使います

pom.xml へライブラリ追加

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.10.19</version>
</dependency>

上記でOKです
使えるようになったら早速試してみます

verify

verifyは作成した Mock オブジェクトが正確に何回動作したかをチェックするための機能です
とりあえず以下がverifyを使ったサンプルコードです

public void testVerify() {
  List mockedList = mock(List.class);
  mockedList.add("one");
  mockedList.clear();
  verify(mockedList).add("one");
  verify(mockedList).clear();
}

まずはじめに冒頭でimport static org.mockito.Mockito.*;で書いておくといいと思います
Mockitoクラス配下の static なメソッドを使う機会が
多いためです

mockメソッドの引数に Mock オブジェクトとして作成したクラスのオブジェクトを渡します
サンプルのList.classjava.util.Listの List クラスです
作成した Mock オブジェクトは普通にそのクラスに存在しているメソッドをコールすることができます
作成した Mock オブジェクトに対してadd, clearを1回ずつコールします

そしてその後でverifyを使って Mock オブジェクトが正しく動作したかを評価します
verifyの引数に評価したい Mock オブジェクトを指定して、続けて評価したいメソッドをコールします

verify(mockedList).add("one");

こうすることで何が起きているかいうと

mockedList の add メソッドが引数 “one” で1回ちゃんとコールされているか

を評価することができます
なので、例えばverifyする前のadd

mockedList.add("two");

こんな感じでコールし直すように変更するとverifyが失敗することが確認できると思います

verifyは引数をもう一つ持つことができて評価する回数を指定することができます

verify(mockedList, times(2)).add("one");

Mock クラスのtimesというメソッドを使って評価された回数を指定できます

when

whenはある Mock オブジェクトのメソッドがコールされたときにこういう値を返しますという振る舞いを設定することができる機能です
とりあえず以下がwhenを使ったサンプルコードです

public void testWhen() {
  App app = mock(App.class);
  when(app.getAppname()).thenReturn("myapp");
  System.out.println(app.getAppname());
}

Mock オブジェクトを作成してwhenメソッドを呼び出します
引数に作成した Mock オブジェクトのあるメソッドを指定します
指定するメソッドは必ず返り値を保つ必要があるためvoidのメソッドでwhenを利用することはできません
whenで返り値を設定した場合、Setter などで値を上書きしたと思ってもwhenで指定した値が取得されます

when(app.getAppname()).thenReturn("myapp");
app.setAppname("hoge");
System.out.println(app.getAppname());

-> myapp が出力される

要するにあるメソッドの戻り値を意図的に設定することができます
他にも Exception を投げたり引数を元に複雑な返り値を設定できるthenAnswerがあります
※参考 : http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html

最後に

Java の Mock 系のライブラリは他にもいろいろあります (JMock, EasyMock etc…)
他のライブラリも使って書き方や機能を比較してみるとおもしろいかも
今回

2015年7月28日火曜日

ニフティクラウド RDB で utf8_mb4 が使えるか試してみた

概要

ここの記事を参考にニフティクラウドRDBでも utf8_mb4 が使えるか試してみました
ちなみに utf8_mb4 は 4 バイト長の utf8 文字をサポートする文字コードで emoticon (絵文字) や 第4水準漢字が使えるようになるみたいです

環境

  • Mac OS X 10.10.4
  • MySQL Client 14.14 Distrib 5.6.25
  • MySQL Server 5.6.22 (ニフティクラウド RDB)

RDBの作成

コントロールパネルから簡単に行えるので詳細は割愛します
流れだけ紹介します

  1. コントロールパネルにログインしDBサーバの一覧から「DBサーバー新規作成」
  2. 入力する内容はとりあえず適当でOK (後で utf8_mb4 を有効にした DB パラメータグループに変更します)

今回はテストなのでスペックは mini として冗長化やディスク拡張はしない最小限のスペックで作成しました
また、DB名やユーザ名も適当に指定しました

30分ほどで作成できるので待ちます

utf8_mb4 用の DB パラメータグループの作成

DBサーバーが作成できたら DB パラメータグループを作成します
今回は utf8_mb4 を設定した専用のパラメータグループを作成します
DBパラメータの一覧から「DBパラメーターグループの新規作成」として作成します
名前は「utf8mb4」とでもしておきましょう
作成できたらパラメータを変更していきます

作成した DB パラメータグループをチェックしてプルダウンから「DB パラメータグループの編集」を選択します
ここで以下4パターンのパラメータを変更します

character 系パラメータの変更

検索ボックスに「character」と入力してください
ここで表示された以下5つの項目を utf8mb4 に変更します

  • character_set_client
  • character_set_connection
  • character_set_database
  • character_set_results
  • character_set_server

変更はプルダウンの一覧から選択してください

set_character.png

collation 系パラメータの変更

次に検索ボックスに「collation」と入力してください
ここで表示された以下2つの項目を utf8mb_general_ci に変更します

  • collation_connection
  • collation_server

変更はプルダウンの一覧から選択してください

set_collation.png

skip-character-set-client-handshake パラメータの変更

3つ目は検索ボックスに「skip-character-set-handshake」と入力してください
このパラメータの値を 1 に変更します

set_handshake.png

init_connect パラメータの変更

最後に検索ボックスに「init_connect」と入力してください
このパラメータは文字列を直接入力する必要があるので「SET NAMES utf8mb4;」と入力してください

set_init_connect.png

上記の作業は一度に変更してもOKですし、1つずつ保存してから実施してもOKです
全項目が設定できたら DB パラメータグループの設定は終わりです

DB サーバの DB パラメータグループを変更する

DB サーバーの一覧に移動します
作成待ちになった DB サーバーができていれば DB パラメーターグループを変更します
DB サーバーをチェックして「設定変更」をクリックします

DB パラメーターグループを変更できる箇所があるのでプルダウンから作成した DB パラメーターグループを選択して変更を適用します

これで DB サーバーに適用されている DB パラメータグループの変更は完了しました
ただ、まだ MySQL 自体にそのパラメータが適用されていないので一度 DB サーバー自体を再起動します
これも DB サーバーをチェックして「DBサーバー再起動」を選択すればOKです
再起動は数分で完了します

MySQL クライアントで接続して動作確認してみる

今回は Mac で動作確認しています
mysqlコマンドがインストールされていない場合はbrew isntall mysqlでインストールしましょう

では接続してみましょう
接続方法は普通の MySQL と同じです

mysql -u usename -p db_name -h grobal_ip_address

username, db_name, grobal_ip_address は作成された DB サーバーの情報を入力してください
パスワードを入力して接続できればOKです

文字コードの設定を確認してみる

statusコマンドで確認してみましょう

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.6.25, for osx10.10 (x86_64) using  EditLine wrapper

Connection id:          41
Current database:       utf8mb4_test
Current user:           username@xxx.xxx.xxx.xxx
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.6.22 MySQL Community Server (GPL)
Protocol version:       10
Connection:             111.171.222.67 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               3306
Uptime:                 1 hour 31 min 41 sec

Threads: 1  Questions: 135  Slow queries: 0  Opens: 73  Flush tables: 1  Open tables: 65  Queries per second avg: 0.024
--------------

utf8mb4 になっていることが確認できます
では実際に絵文字が登録できるか試してみます

絵文字を登録してみる

まず適当にテーブルを作成しましょう

CREATE TABLE test_utf8mb4 (str VARCHAR(50)) CHARACTER SET utf8mb4;

このテーブルにデータを入れてみます
コマンドは以下の通りです
※絵文字を使用しているため画像になります

insert_emoticon.png

完了したらSELECTしてみましょう

select_emoticon.png

絵文字が登録されていることを確認できました
ちなみに utf8mb4 になっていない MySQL に対してもテストしてみたのですが、以下のように絵文字は登録されないことが確認できました

select_empty_character.png

最後に

ニフティクラウドRDBでも utf8mb4 が動くことを確認できました
サーバ側の設定はコンパネおよびターミナルでできるのですが、動作確認時の絵文字の入力が Mac じゃないとちょっと大変かもしれません
Mac の場合Shift+Cmd+Spaceで絵文字一覧がでるのでそこから選択するだけ絵文字入力できるので楽です

2015年7月27日月曜日

Spring でファイルアップロードを PUT メソッドで処理する方法

概要

Spring で multipart/form-data + MultipartFile を扱う場合は、通常は POST メソッドでなければなりません
どうやら MultipartFile は POST メソッドでないと操作できないようです
実装上そもそも不要なケースが多いですが、PUT メソッドで multipart/form-data を受け取る方法を紹介します

環境

  • Mac OS X 10.10.4
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

サンプルプロジェクト作成

過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください

コーディング

@RequestMapping に PUT で multipart/form-data を受け取る定義を記載する

@RequestMapping(value = "/**", method = {RequestMethod.PUT}, headers = "content-type=multipart/form-data")
@ResponseBody
public void receivePutMulti(@RequestParam(value = "file", required = true) MultipartFile file) {
  ...
}

受け取りたいURLマッピングに上記のようにメソッド名とヘッダーのタイプを指定します
今回はファイルのアップロードを想定しているため MultipartFile を受け取るように指定します
返り値は jsp を返却したい場合は String 型を返り値に指定し@ResponseBodyを削除してください

ちなみにこの状態で以下のように PUT メソッドでファイルのアップロードを実行しようとすると500エラーになります

curl -v -X PUT -H "Content-Type: multipart/form-data" http://localhost:8080/test/put/ -F "file=@pom.xml"
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?

このエラーがでないように設定していきます

servlet-context.xml に独自 MultipartResolver を指定する

<beans:bean id="multipartResolver" class="com.sample.test.ExtendedMultipartResolver">
</beans:bean>

Multipart なデータは MultipartResolver というクラスでどう受け取るかのルール付けがされており、このクラスを拡張することで PUT メソッドでも MultipartFile が受信できるようにします

次に指定した独自の MultipartResolver クラスを作成していきます

独自 MultipartResolver クラスの作成

pom.xml に定義を追加する

<!-- FileUpload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

独自の MultipartResolver を作成するのに commons-fileupload が必要になるので pom.xml に追記します
既存の<dependencies>タグ内に追記してください

ExtendedMultipartResolver クラスの作成

今回はcom.sampe.test.ExtendedMultipartResolverとして作成します
とりあえず以下がサンプルになります

package com.sample.test;

import javax.servlet.http.HttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public class ExtendedMultipartResolver extends CommonsMultipartResolver {

    @Override
    public boolean isMultipart(HttpServletRequest request) {
        if (request != null) {
            String httpMethod = request.getMethod().toLowerCase();
            // test for allowed methods here...
            String contentType = request.getContentType();
            return (contentType != null && contentType.toLowerCase().startsWith("multipart"));
        } else {
            return false;
        }
    }
}

ポイントは@OverrideしているisMultipartメソッドでこの中でHttpServletRequestからアクセスしているメソッド情報を取得して PUT メソッドでもtrueを返却するように実装し直します
サンプルは全メソッドで multipart/form-data を許可する設定になっており特にメソッド名に応じてfalseを返却するような if 分岐は入れていません

動作確認

ここまで実装できたらアプリを再起動してコードを反映しましょう
先ほどの PUT + multipart/form-data の curl のサンプルリクエストを投げてみましょう

すると先ほどのエラーにはならず定義したメソッド内の処理が実行されていることが確認できると思います

最後に

ちょっと調べてみたんですが Spring がデフォルトで実装していないのは RFC 的にそうなっているため(?) みたいな記事があったような気がします
詳細には調べていないので、わかりませんが PUT で multipart/form-data は基本は受け取らないんですかね
そもそもそれは実装が悪いってことになるのか

参考サイト

2015年7月23日木曜日

Spring の @RequestMapping で OPTIONS メソッドを処理する方法

概要

Spring で OPTIONS メソッドのリクエストを受け取る方法を紹介します
普通に@RequestMappingmethod=RequestMethod.OPTIONSを指定するだけだとダメでした

環境

  • Mac OS X 10.10.3
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

サンプルプロジェクト作成

過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください

コーディング

@RequestMappingにOPTIONSメソッドを追加する

これだけだとダメという話をしましたが、これがないと始まらないので定義します

@RequestMapping(value = "/", method = {RequestMethod.GET, RequestMethod.OPTIONS})

既存のメソッドと同じマッピングで受け取る場合は中括弧を使って定義してください
もちろん上記を追加しただけだと、まだリクエストを受け取ることができません

web.xml に定義を追加する

web.xml<servlet>タグに以下を追記します

<servlet>
  <servlet-name>appServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>dispatchOptionsRequest</param-name>
    <param-value>true</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

おそらくweb.xml内に<servlet>タグはすでにあると思います
<servlet-name><servlet-class>がある場合は新規で追加しなくてOKなので過不足分を既存の<servlet>タグ内に追記すればOKです

web.xmlはSTSで作成していれば、src/main/webapp/WEB-INF/web.xmlにあります

動作確認

書き換えが完了したらアプリを再起動してOPTIONSメソッドのリクエストが処理されるか確認してみましょう
自分はいつもcurlコマンドで確認しますが、curl の場合は以下のようにするとOPTIONSメソッドのリクエストが送信できます

curl -v -X OPTIONS http://localhost:8080/test/

これで@RequestMappingアノテーションが付与されたメソッドが実行されればOKです

Tips

MockMVCを使っている場合に有効にする方法

上記の手順を実行すれば実際のアプリ側でOPTIONSメソッドのリクエストを取得することができます
ただ、テストの場合は有効になっていないようで別途有効にする必要があります
MockMVCを使っているのであればテスト用のMockMVCのオブジェクトを生成する際に.dispatchOptions(true)を指定します

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();

これを実施しないとテスト時にOPTIONSメソッドが受け取れませんでした

最後に

OPTIONSメソッドはリソースがサポートしているメソッドの一覧を返却するために用意されたメソッドです
OPTIONSメソッドのリクエストのときにレスポンスボディを返却することは基本ないと思いますが、やりたい場合は今回紹介した方法で実現できると思います

2015年7月22日水曜日

開発合宿してみたいメモ

概要

  • 非日常的な環境で開発をすることで、おそろしく開発効率が上がるのではないか
  • 「仕事」として行く気はないので気軽に行こう
  • 成果のルールは決めない
  • 南国でやりたい

唯一のルール

  • 必ず最後に何をしたのか、していないのか、作ったのかなど「発表」をすること
  • 昼飯と晩飯はみんなで食べましょう

欲望メモ

  • 仕事はしたくない、とにかく自分がやりたいことをやってみよう
  • オフィスでない非日常的な環境で開発することで効率アップ(するかどうか)を体験してみる
  • あれ、オレリモートでも仕事できるじゃん
  • OSS、クローズドは問わない
  • ホテルとかじゃなくて、Airbnbとかでコテージとか借りてやりたい(ホテルでもいいと思うけど)
  • 食事、睡眠以外の時間は基本的にフリーでコーディング、場所も問わない、飯の時間は決めておくし、みんなで一緒に食う
  • フリー時間はコーディングすらしなくてもOK、遊んでもOK
  • コーディングスタイルは自由、ペアでもチームでも個人でもいい
  • メンバーは一応知人を中心に 3 - 5人、多すぎはダメ
  • コーディング中はみんなバラバラだと思うので連絡は Slack とかのチャットを使おうと思う
  • 1泊2日 or 2泊3日
  • あえて土日返上
  • 集合解散は最悪、現地集合 - 解散でもOK
  • 開発環境(ネットワーク、ディスプレイ)は知らん、自分で何とかする
  • 移動とかも知らん
  • 最後の発表はフリーフォーマット、特にテーマはなし
  • たぶん単発、定期的にやる気はないです
  • ぶっちゃけ自分が開発したいだけ