shiroを使おう
公式HPトップ
個人的にこのページがおすすめ 【shiro.iniの書き方】
1.shiroとは
Javaの、セキュリティ関連の、フレームワークです。
つまりJavaでの開発時に、セキュリティ関連を簡単に扱いたい!って時に使えます。
セキュリティ関連とは、ログイン関係だったり、APIの認証など
主に認証、承認、暗号化、セッション管理を簡単に扱えるようにしてくれます。
2.つまり何ができる?
・ログイン時のパスワードの暗号化(正確にはハッシュ化)
・ログインし、セッションに情報を保持
・ユーザの権限をセッションに保持
・DBからユーザの役割コードを取得
・役割コードに基づき閲覧ページを制御
・APIでのBasic認証などを制御
などです
ざっくりですが、一般のWebアプリではこの辺がメインになるかと。
というかこの辺をメインにshiroが作られていると思いますたぶん。
ようは、ユーザ管理やAPI認証がとても楽になる、ということですね
3.どんな感じで使うの
基本的には、「shiro.ini」という設定ファイルに
設定を記述していきます。
以下、設定のイメージ(公式より)
# =======================
# Shiro INI configuration
# =======================
[main]
# Objects and their properties are defined here,
# Such as the securityManager, Realms and anything
# else needed to build the SecurityManager
[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined
# set of User accounts.
[roles]
# The 'roles' section is for simple deployments
# when you only need a small number of statically-defined
# roles.
[urls]
# The 'urls' section is used for url-based security
# in web applications. We'll discuss this section in the
# Web documentation
mainには基本的な設定、例えば
・参照先のDB(DataSource)
・接続の設定(JdbcRealm)
・呼び出すSQL
・パスワードハッシュ化のクラス
usersはあまり使わないイメージですが、アカウント関連の設定みたいですね
rolesは役割の設定
urlsには、ページ閲覧の承認ですね。例えば
・A.htmlにはX権限とY権限が必要
・ログインにはX権限が必要
・Basic認証にはY権限が必要
などです
そして、iniファイルの設定として
jdbcRealmを、「DefaultJdbcRealm.java」クラスにしたとすると
実際に実装したDefaultJdbcRealm.javaの内容に基づいた機能が呼び出されるわけです
早い話が、「shiro.iniには鍵と、鍵を使う順番が書いてある」というイメージです
伝わりにくかったらすみません...
4.具体的にはどうやって使うの
お待ちかね具体例。
よく使うので、mainとurlsの2セクションを例に取ります
[main]
# SHA-256のハッシュに関する設定。すなわち、パスワードハッシュ化、照合の設定
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
# DB接続の設定
myRealm = com.company.security.shiro.DatabaseRealm
# DB接続のタイムアウト設定
myRealm.connectionTimeout = 30000
# DB接続のユーザ名
myRealm.username = jsmith
# DB接続のパスワード
myRealm.password = secret
# DB設定の、認証に使うクラスを$「クエリ」で設定
# 上でsha256MatcherをSha256CredentialsMatcher.javaにしているので
# Sha256CredentialsMatcher.javaが設定されることになる
myRealm.credentialsMatcher = $sha256Matcher
# shiroのセッションは、セキュリティマネージャという領域に格納される
# セキュリティマネージャ内の、セッションの、共通タイムアウト設定
securityManager.sessionManager.globalSessionTimeout = 1800000
テキスト内にだいたい書きましたが、補足として
・だいたいがshiroの用意したJavaクラスで大丈夫です
・なので公式のものをそのまま使えます
・Javaクラスの中の仕組みが知りたかったら、適当にどこかでインポートしてコード見れます
そして、独自でDB接続を用意したい場合は
[main]
ds = org.apache.shiro.JndiObjectfactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = オリジナルDBリソース名
jdbcRealm = 自身で用意したjdbcRealmのjavaクラスのフルパス
jdbcRealm.permissionsLookupEnabled = true
# ログイン認証時にはしらせるSQL, ?を引数として、オリジナルjdbcRealmのJavaクラス内でセットできる
jdbcRealm.authenticationQuery = "SELECT 項目 FROM テーブル WHERE 項目 = ? AND 項目 = ?"
jdbcRealm.userRolesQuery = "SELECT 項目 FROM テーブル WHERE 項目 = ?"
# 接続先DBを、上記で設定したdsにする
jdbcRealm.dataSource = $ds
# shiroならではのセキュリティマネージャって領域のDB接続も、今設定してるjdbcRealmにしちゃう
securitymanager.realms = $jdbcRealm
# パスワード一致不一致を確かめるものも設定
jdbcRealm.credentialsMatcher = $自分で設定したパスワード一致のやつ、上でいうsha256matcher
shiroの特徴として
セキュリティマネージャ
という領域があります
この中に、セッションだったりDBから取得した情報をいろいろ持っています
ハッシュ化のソルトなどもこの中に格納したりしていて
よく使うHttpSession
も、セキュリティマネージャの中に入れてあげることで
どの状態からでもget/setできます
また、
jdbcRealm.authenticationQuery = "SELECT 項目 FROM テーブル WHERE 項目 = ? AND 項目 = ?"
のように
引数に複数の値をセットしたい場合ですが
shiro既存のjdbcRealmでは
java標準のpreparedstatementを用いて、ResultSetを設定してSQLのクエリを生成しているのですが
既存では引数が1つしかありませんので、
jdbcRealmを既存のままSQLの?引数を2個以上にするとエラーになります
なので...
org.apache.shiro.realm.jdbc.JdbcRealm.javaクラス
をextendsした独自のjdbcRealmクラスを作成し
protecrted Authorizationinfo doGetAuthorizationInfo(PrincipalCollection principals)
をOverrideし
while文でPreparedStatementをセットしているメソッドの引数を増やします
(実際のコードは諸事情によりここには記載しません、ご了承ください)
続いてurlsに移ります。
公式のリファレンスが別ページに移動しているのでご参照あれ
[urls]
/index.html = anon
/user/create = anon
/user/** = authc
/admin/** = authc, roles[administrator]
/rest/** = authc, rest
anonは制限なし
authcは標準で、ログインに成功した人、という設定にしてくれています
また
roles[administrator]
は
DB内に役割コードとして、文字列「administrator」を持っていたとして
ログインした人の役割として「administrator」を所持している場合のみ閲覧可能
ということです
別に文字列の内容は何でもいいので
[urls]
/独自ページ.html = roles[独自権限]
とすれば、役割コードを取得するSQLで「独自権限」という文字列をSELECTできた場合に
独自ページ.htmlへの遷移が可能になるわけですね
また、/rest/**
と指定できることからわかるように
遷移先のhtmlファイルをディレクトリごとの分けて整理することで
Aディレクトリ配下のページは権限A
、Bディレクトリ配下のページは権限B
というように
一括で分類できるわけです
また、JSFではxhtml内で
<shiro:hasRole name="auth"></shiro:hasRole>
<shiro:hasAnyRoles name="auth"></shiro:hasAnyRoles>
というようにくくることで
指定した権限を持っている場合のみ、その要素を表示
と制御できる
これにより、ページ遷移の制御+ページ内部の閲覧制御をこなすことができる
かなり楽にしてくれますね
以上が今回のまとめになります。
最後まで読んでいただき、ありがとうございました。
修正点があれば随時対応していきます!