Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【Spring Security】セッションのデフォルト有効期限は30分しかない

f:id:rennnosukesann:20181220183020p:plain

というかServletの仕様ですね。

Spring Securityにおけるセッションの有効期限

Spring Securityでは、セッション情報をJava Servletで扱うようなHttpSessionとして扱えます。またセッションに紐づく情報は、クッキーであるHttpCookieオブジェクトとして扱えます。

    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    HttpServletRequest request = attr.getRequest();
    Session session = request.getSession();

    HttpServletResponse response = attr.getResponse();
    Cookie cookie = new Cookie();
    cookie.setPath("/");
    response.addCookie(cookie);

ただしこのセッション、デフォルトでは有効期限が30分となっているため、より長い期限を設けたい場合は明示的に有効期限を定義する必要があります。

簡単な有効期限の設定方法として、 application.properties(yml) に記述する方法があります。

server.session.timeout=3600 // 秒数で指定(負の数で無限)

また別の方法として、 HttpSession に直接指定する方法もあります。

    // セッションタイムアウト時間を秒数で指定
    //(負の数で無限)
    session.setMaxInactiveInterval(3600);

各クッキーの有効期限を設定する

セッションそのもの(セッションID)の有効期限ではなく、セッションに紐づく個々のクッキーの有効期限にも気をつけるべきです。

こちらも同様に application.properties(yml) に記述できます。

server.session.cookie.max-age=3600

一回ハマったはずなのに、完全に忘れてた。。。

ブログタイトルとデザインを更新しました

突然ですが、本ブログのタイトルと、ブログ全体のデザインを更新させていただきました。

f:id:rennnosukesann:20190113185422p:plain

今までははてなブログで提供されていたデフォルトのブログテーマを使わせていただきましたが、そろそろデザインを変えたいと思い、またどうせ変えるなら自分でカスタムしたいという思いもあり、ブログテーマを一から作ってみることにしました。

ブログデザインを作成するにあたり、いくつか知見があったので共有します。

HTMLをすべて自由記述できるわけではない

はてなブログでは、既存のHTMLの編集はほぼできないようになっています。例えば個人で一からHTMLのテンプレートを作成し、それをアップロードする・・・といった機能はついていません。

これは、既存のHTMLテンプレートを個々にいじられてしまうと、はてなブログとして運用していくのに必要なタグや要素が削除されてしまい、思わぬレイアウトの崩れ等の問題が発生してしまうためかと思われます。

そのため新しくブログデザインを作成する場合には、すでにあるブログテンプレートに対してスタイリングを行うCSSをメインに作っていくことになります。

作成したCSSは、ブログ管理画面のサイドメニュー「デザイン」->「カスタマイズ(レンチのアイコン)」タブ->「デザインCSS」のテキストボックスに貼り付ければ適用できます。

f:id:rennnosukesann:20190113184214p:plain

f:id:rennnosukesann:20190113184233p:plain

とはいえHTMLを全く編集することができないわけではなく、一部ヘッダーなどのコンポーネントの直下などに追加のHTMLを記述することはできます。

HTMLを追加記述可能な箇所は、

  • タイトル下(ヘッダ)
  • 記事上(記事)
  • 記事下(記事)
  • フッタ

の4箇所になります。

編集箇所は先ほどと同じブログ管理画面の「デザイン」メニューになります。例えばヘッダ直下にHTMLを新しく追加したい場合には、下記のように「HTMLを記述できます」と書かれたテキストボックスにHTMLを記述します。

f:id:rennnosukesann:20190113185625p:plain

はてな公式がボイラープレートを用意してくれている

はてなブログのデザインテーマを作成するにはCSSを貼り付ければ良い、ということはわかりました。が、CSSをちまちまと書いていきながら、編集したCSSを管理画面に貼り付けて、逐一チェックする・・・というのはちょっと骨が折れます。

そこで、はてなブログ公式が用意してくれているボイラープレートを拝借します。

github.com

このボイラープレートではSCSSによるスタイルシート作成環境を提供してくれています。ボイラープレートをクローン後、 npm で必要なパッケージをインストールしてサーバを立ち上げるだけで、SCSS編集時に自動でCSSを生成してくれます。立ち上げたローカルサーバへのパスをデザインCSSとしてブログデザインに適用すれば、SCSSをビルドするたびにプレビュー画面に最新の編集状況を表示できます。

詳細ははてなブログ公式ヘルプブログで紹介されています。ボイラープレートの導入手順を紹介している他、編集の手引きまでしてくれています。

help.hatenablog.com

レスポンシブデザインも対応可能(今はしてないけど。。。)

はてなブログのデザインテーマにはレスポンシブデザインの有無が設定できます。

ブログ管理画面のサイドメニュー「デザイン」->「スマートフォンスマホのアイコン)」タブ->「詳細設定」の項目で「レスポンシブデザイン」のチェックを入れます。

f:id:rennnosukesann:20190113191931p:plain

次に、ブログ管理画面のサイドメニュー「デザイン」->「カスタマイズ(レンチのアイコン)」タブ->「デザインCSS」の先頭に下記コメントを追加します。

/* Responsive: yes */

これで、現在のブログがスマホ上のブラウザであってもPCブラウザと同じスタイルで表示されるようになります。

レスポンシブデザインを考慮していないサイトの場合、PCブラウザと同じ表示の仕方でスマホブラウザ上にブラウジングされてしまうため、レスポンシブ対応していないデザインの場合はOFFにすることをおすすめします(僕も現在はそうしています)。


僕がブログデザイン作成で得た治験はざっとこんな感じです。

ブログデザイン作るのは楽しいですね。

まだレスポンシブデザイン未対応なので、今度はレスポンシブ対応も頑張ってみようかと思います。

【Docker】ローカル環境上のイメージ/コンテナを全て削除する

f:id:rennnosukesann:20190108224132p:plain

ローカルにあるDockerイメージ/コンテナを全て削除するコマンド。メモ。

# Dockerイメージの全削除
$ docker rmi $(docker images -aq)

# Dockerコンテナの全削除
$ docker rm $(docker ps -aq)

DockerHubにあるイメージをいろいろ試していると、どうしてもローカルのイメージやコンテナがいっぱいいっぱいになってしまいがち。 特にコンテナは一旦きれいにしたい場合が多いので、重宝します。

【Kotlin/Spring】Kotlin版SpringBoot開発環境を構築する

f:id:rennnosukesann:20190106130012p:plain:w300    f:id:rennnosukesann:20181220183020p:plain:w300

Kotlin版Spring Boot開発環境構築のメモです。

検証環境はMac OS X Mojave 10.14.2 になります。

IntelliJ IDEのインストール

今回はIDEとしてIntelliJを使用します。 IntelliJはKotlinの開発元であるJetbrain社が開発していることもあって、Kotlinのサポートはバッチリです。

下記リンクより遷移後、DownloadボタンからIntelliJをダウンロードできます。

www.jetbrains.com

プロジェクトの作成

次に、Spring InitializerからSpringプロジェクトの雛形を取得します。

取得するプロジェクトに関して、いくつかオプションを選択していきます。

f:id:rennnosukesann:20190109194245p:plain

まずビルドツールとして Maven Gradle のうち何れかを選択します。今回は Gradle のプロジェクトを作成していきます。

f:id:rennnosukesann:20190109194422p:plain

次に言語選定です。主要なJVM言語 Java Gloovy Kotlin から選択できます。 今回はKotlinで書くので「Kotlin」 を選択。

f:id:rennnosukesann:20190109194503p:plain

次にSpringのバージョンを選択します。今回は安定版の 2.1.1 を選択します。

f:id:rennnosukesann:20190109194630p:plain

プロジェクトのメタ情報について設定します。

GroupはGradleのGroupIDとなり、プロジェクトを一意に識別するためのものです。プロジェクトのソースファイルを含めるパッケージと同一にすることが慣習となっています。

ArtifactIDはいわゆるプロジェクト名です。

メタ情報に関する記述は下記参照。

maven.apache.org

f:id:rennnosukesann:20190109194810p:plain

最後にSpringに追加したいライブラリを入力・選択します。

今回はWeb(Webページ生成/APIインタフェース等のWeb関連機能)、JPA(永続化機能)、Security(認証機能)を選択しました。

f:id:rennnosukesann:20190109195844p:plain

最後に「Cenerate Project」ボタンを押して、zipファイルをダウンロードしてください。

f:id:rennnosukesann:20190109195925p:plain

プロジェクトを開く

次は、ダウンロードしたプロジェクトをIntelliJで開きます。

ダウンロードした圧縮済みプロジェクトを解凍し、解凍後のプロジェクトを任意のディレクトリに配置してください。 その後、ダウンロード(+インストール)したIntelliJを起動し、起動後ダイアログ中の「Open」をクリックしてください。

f:id:rennnosukesann:20190109201202p:plain

するとディレクトリ選択のためのファイルダイアログが開かれます。 ここでIntelliJで開きたいプロジェクトを選択。

f:id:rennnosukesann:20190109201327p:plain

「OK」をクリック。

f:id:rennnosukesann:20190109201523p:plain

これでプロジェクトがIntelliJ上に読み込まれました。

f:id:rennnosukesann:20190109202133p:plain

あとは開発するのみ!

ローカルでSpringアプリケーションを起動

実際にアプリケーションをローカルで起動してみます。

起動の前に、 build.gradle を少し編集します。 Spring Data JPAライブラリを読み込むとDBの設定が必要になるため、 今回は一旦外しておきます。

f:id:rennnosukesann:20190109234614p:plain

「View」->「Tool Windows」->「Gradle」 を選択。

f:id:rennnosukesann:20190109234745p:plain

「(プロジェクト名)」-> 「Tasks」->「application」->「bootRun」を右クリックし、「Run '(プロジェクト名)[bootRun]'」 を選択。

f:id:rennnosukesann:20190109234812p:plain

するとビルド・アプリケーションの起動が始まります。

23:39:41: Executing task 'bootRun'...

:compileKotlin
w: ... ated
:compileJava NO-SOURCE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)

...

2019-01-09 23:40:22.533  INFO 31168 --- [           main] c.r.n.rpg.rpgkit.RpgKitApplicationKt     : Started RpgKitApplicationKt in 18.3 seconds (JVM running for 19.039)

アプリケーションの起動はこれで成功です!

参考文献

https://start.spring.io/

maven.apache.org

【Docker】イメージビルド時にキャッシュを使用しない

f:id:rennnosukesann:20190108224132p:plain

メモ。

Dockerイメージ作成時、デフォルトだと過去のビルドキャッシュが存在する場合そちらを使用してしまいます。

$ ls
Dockerfile
$ docker build -t hoge .
Step 2/20 : COPY entrypoint.sh /sbin/entrypoint.sh
 ---> Using cache
 ---> 5214f6bedefd

これにより、コマンドの実行結果やファイル内容の反映が上手くいかない場合があります。 --no-cache を指定することで、キャッシュが存在する場合も無視してビルドを実行できます。

$ docker build -t hoge . --no-cache
 ---> 5d870d6990ba
Step 2/20 : COPY entrypoint.sh /sbin/entrypoint.sh

以上です。

【Kotlin】Java(8) -> Kotlinやってみて「良い」と思ったことリスト

f:id:rennnosukesann:20190106130012p:plain:w500

Kotlinをやっていて、Java(8)と比較して良いな、と思った部分を書きました。

null許容型

Swiftなどにもありますが、Kotlinではnull許容型が定義されており、それと対を成すようにデフォルトの型宣言ではnullが許容されないようになっています。

val hoge: String = null // Error:(9, 23) Null can not be a value of a non-null type String
val hoge: String? = null // OK 

エルビス演算子(?:)

オペランド(被演算子)がnullのときのデフォルト値を設定できる

String fuga = hoge == null ? "hoge is null" : hoge;

val fuga = hoge ?: "hoge is null"

第一級関数

Kotlinは関数を言語仕様に持ち、かつそれらを第一級関数として扱えます(値として扱える)。

fun hoge(arg1: String) {
    println(arg1)
}

fun main(args: Array<String>) {
    val func = ::hoge // Javaのメソッド参照のように渡す
    func("hoge")
}

if式

Scalapythonのように、ifが式なので返り値を持ちます。

val isHoge = true;
val hoge = if (isHoge) "hoge" else "not hoge"

文字列テンプレート

JavaScript言語仕様が持つ文字列テンプレートをKotlinでも使用できます。 文字列リテラル内で $ を使って変数を文字列として埋め込みます。

val message = "Hello, Kotlin!"
println("Welcome to Kotlin world : $message")

${} を使用すると、カッコ内に式を使用できます。

val kotlin = "Kotlin!"
val java = "Java"
val isKotlin = true
println("Hello ${if (isKotlin) kotlin else java}")

クラスフィールドにデフォルトでアクセサがつく

immutableフィールド val で宣言した場合はgetterのみが、 mutableフィールド var で宣言した場合はsetter+getterが生成されます。 Kotlinでは暗黙的にgetter/setterが呼ばれます。

class Gorilla(
    val name: String,
    var isAdult: Boolean // getter + setter
)


fun main(args: Array<String>) {
    val gorilla = Gorilla("ゴリラ", true)
    
    // 暗黙的なgetter呼び出し
    println(gorilla.name)  // ゴリラ
    println(gorilla.isAdult) // true
    
    // 暗黙的なsetter呼び出し
    gorilla.isAdult = false
    println(gorilla.isAdult) // false
}

値forループの廃止

言語仕様で for (int i = 0; i < 10; i++) のような繰り返し変数をインクリメントしていく for 文が廃止されており、基本的に拡張forループのみを使用することになります。

Kotlinでfor文による値のインクリメントは .. 演算子によるレンジによって実現できます。

for (i in 1..10) {
    println(i) // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
}

レンジは逆順・数値飛ばしが可能です。

for(i in 10 downTo 1) {
    println(i) // 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
}
for(i in 1..10 step 2) {
    println(i) // 1, 3, 5, 7, 9
}

レンジは閉区間であり、.. 演算子の右側の値を数列に含みます。 開区間のレンジを作る場合、 until を利用します。

for(i in 1 until 10) {
    println(i)  // 1, 2, 3, 4, 5, 6, 7, 8, 9
}

分割代入

オブジェクトプロパティを複数の変数に代入することができます。

fun divMod(a: Int, b: Int) : Pair<Int, Int> {
    return Pair(a / b, a % b)
}

fun main(args: Array<String>) {
    val (div, mod) = divMod(10, 3)
    println("div: $div , mod: $mod")
}

when式

Javaではif/switch文で処理できた複数の分岐処理が、Kotlinではwhen式と呼ばれる言語仕様で実装できます。 when式は式として評価されるので分岐先で結果を返す・変数に入れるなどの操作ができます。 whenはJavaのswitch文のように並列に記述できます。

fun main(args: Array<String>) {
    val num = 3;
    println(fizzbuzz123(num)) // 
}

fun fizzbuzz123(num: Int): String{
    return when (num) {
        1 -> "fizzbuzz"
        2 -> "fizz"
        3 -> "buzz"
        else -> "$num"
    }
}

また引数を省略することで、値マッチングの代わりに条件式による分岐が可能になります。

fun main(args: Array<String>) {
    val num = 3;
    println(fizzbuzz(num))
}

fun fizzbuzz(num: Int): String{
    return when {
        num % 15 == 0 -> "fizzbuzz"
        num % 3 == 0 -> "fizz"
        num % 5 == 0 -> "buzz"
        else -> "$num"
    }
}

名前付き引数/デフォルト引数

名前付き引数・デフォルト引数もサポートされています。

fun add(a: Int, b: Int = 1) :Int {
    return a + b;
}

fun main(args: Array<String>) {
    println(add(1,2)) //3
    println(add(1)) //2
    println(add(a = 4,b = 2)) // 6
}

全般的に他言語で実装済みのモダンで使いやすい言語仕様が入っている印象でした。 まだまだ良いところがありそうなので、追記するかもしれません。

【Kotlin】Kotlin CLIでKotlinをJavaバイトコードにコンパイル/実行する

f:id:rennnosukesann:20190106130012p:plain:w500

今日はじめてKotlinを触ってみたのですが、その際に使用したKotlin CLIによるコンパイルと実行のメモです。

Kotlin CLIのインストール

実施環境:Mac OS X Mojave 10. 14.2

brew でインストールできます。

$ brew update
$ brew install kotlin

コンパイル

適当な .kt ファイルを用意します。

hoge.kt
fun main(args: Array<String>) {
    println(args)
}

kotlinc コマンドでコンパイルします(オプションでKotlinランタイムを含めたjarを生成)。

$ kotlinc hoge.kt -include-runtime -d hoge.jar

jar ファイルが生成されるので、Java同様 java コマンドで実行します。

$ ls
hoge.kt hoge.jar
$ java -jar hoge.jar
[Ljava.lang.String;@1b6d3586

コンパイル時に -include-runtime でKotlinランタイムを含めているのは、Kotlinコンパイラコンパイルされて生成されたバイトコードがKotlinランタイムのライブラリに依存しているためです。ランタイムを含めずにそのままコンパイルすると、実行時に kotlin/jvm/internal/Intrinsics クラスが見つからず ClassNotFoundException 例外を送出します。

$ kotlinc hoge.kt
$ kotlinc _hoge.class
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
    at _hoge.main(1_5_1_compile.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

ちなみに kotlinc コマンドを引数なしで実行すると、インタラクティブシェル(REPL)が起動されます。

$ kotlinc
Welcome to Kotlin version 1.3.11 (JRE 1.8.0_131-b11)
Type :help for help, :quit for quit
>>> println("Hello, Kotlin CLI !")
Hello, Kotlin CLI !
>>> :help 
Available commands:
:help                   show this help
:quit                   exit the interpreter
:dump bytecode          dump classes to terminal
:load <file>            load script from specified file

参考文献

kotlinlang.org