ユーザー認証や権限の制御を行うために標準APIとしてJAAS(Java Authentication and Authorization Service) APIがあります。
JAASには、ユーザーが正当であることを確認する認証と、ユーザーの権限に応じて要求を制御する承認の2つの要素があります。
認証で使用する主要APIは以下です。
認証のフローは大まかには以下です。
JAASでは、以下の認証方式(LoginModule)がデフォルトで提供されています。
また、自分で任意の認証方式を作成して使用することもできます。どの認証方式を使うかは、ログインモジュール設定ファイルに記述します。
認証対象(Subject)は、ログイン名などのPrincipalと、パスワード/チケット/公開鍵証明書などのCredentialを持ちます。
承認で使用する主要APIは以下です。
どの認証対象(Subject)に対してどの操作を許可するのかについては、ポリシーファイルに記述します。
許可を得て実行する処理は、インタフェースjava.security.PrivilegedActionを実装するクラスを作成し、そのrunメソッドに記述します。
JAASを使った簡単なプログラムを以下に記述します。このサンプルは、記事「JAAS」を知る、使うで掲載されたものをWindows 7上でJDK 1.6でコンパイル・実行するようにしたものです。認証にWindowsを使用するので、動作はWindowsとなりますが、設定ファイルの変更のみでSolarisやLinuxに対応できるはずです(未確認)。
プログラムは、2つのクラスで構成しています。
AdminClass
mainメソッドを持ち、JAAS認証を行い、JAAS承認のための呼び出しを行う
UserAction
PrivilegedActionインタフェースを実装し、runメソッドでファイルアクセスを行う
また、実行時に参照する3つの設定ファイルがあります。
policy
AdminClassコード中でLoginContextを呼び出すのは認証前なので、ユーザーベースのセキュリティ機構はまだ使えません。そこで、コードベースのセキュリティ機構で許可をしています。
policy.jaas
認証対象(Subject)とその許可内容を定義します。
login.conf
JAAS認証で使用するLoginModule実装を指定します。
このサンプルは、JDK 6がサポートするWindows OSで動作します。このサンプルを実行するときにWindows OSにログインしているユーザーに基づき認証対象(Subject)を取得し、そのSubjectが持つPrincipal(ユーザー情報)に対して権限制御を行います。
Windows OSのログイン情報をそのまま取得するので、このサンプルで別途ユーザーIDやパスワードをユーザーに入力要求することはしていません。
まず、AdminClassのソースコードを以下に示します。なお、コメント、例外発生時の処理は、JAASプログラミングの本筋を簡潔に把握するために省略しています。実際に試してみるときは、最低でもprintStackTrace()を補うなどしてください。
import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.security.auth.Subject; public class AdminClass{ static LoginContext loginContext = null; public static void main(String[] args) { try { loginContext = new LoginContext("NTLogin"); // (1) } catch (LoginException e) { return; } try { loginContext.login(); // (2) } catch (LoginException e) { return; } Subject subject = loginContext.getSubject(); // (3) Subject.doAs(subject, new UserAction()); // (4) } }
import java.security.PrivilegedAction; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class UserAction implements PrivilegedAction<Boolean> { // (1) @Override public Boolean run() { // (2) try { BufferedReader reader = new BufferedReader(new FileReader("AdminClass.java")); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } return Boolean.TRUE; } catch (IOException e) { return Boolean.FALSE; } } }
grant CodeBase "file:${user.home}/jaas/sample1/" { permission java.security.AllPermission; };
JAAS認証を呼び出すAdminClassには、セキュリティ上全権限を与えています。
grant Principal com.sun.security.auth.NTUserPrincipal "Administrator" { permission java.util.PropertyPermission "java.home", "read"; permission java.io.FilePermission "<<ALL FILES>>", "read"; };
Windows OSに"Administrator"ユーザーでログインしていた場合に、システムプロパティ"java.home"の読み出し権限および任意のファイルの読み込み権限を許可しています。
policyファイルの許可を、AllPermissionではなく、AuthPermissionにして、createLoginContextとdoAsの許可を記述したとき、なぜかUserActionのrunメソッド実行中にSecurityExceptionが発生しました。PropertyPermissionでjava.homeにreadが与えられてないというエラーです。しかし、policy.jaasで指定しているはずなのです。原因は不明ですが、記録として残しておきます。
NTLogin { com.sun.security.auth.module.NTLoginModule required; };
LoginContextが使用するLoginModuleを指定します。ここでは、Windowsログインを扱うNTLoginModuleを指定しています。
ソースファイルおよび設定ファイルのディレクトリ構成を以下に示します。
C:/Users/taro/jaas/sample1 +-- action | +-- UserAction.java +-- AdminClass.java +-- login.conf +-- policy +-- policy.jaas
コンパイルをします。
~$ cd jaas/sample1 sample1$ javac -cp action AdminClass.java sample1$
実行します。
sample1$ java -cp action:. -Djava.security.manager \ -Djava.security.policy=policy -Djava.security.auth.policy=policy.jaas -Djava.security.auth.login.config=login.conf AdminClass
[1] | 和田周. Javaの新セキュリティ・メカニズム JAASを知る、使う. Java World 2002.8 2002. |
[2] | Stuart Halloway. JAASの紹介、JAASの使用. JDCテクニカルティップ 2001.7.27号 2001. |
[3] | . JAAS Tutorial. Java 2 SDK, Standard Edition Document |