目的
複数のRoleが定義されているアプリケーションで、各APIごとに使用していいRoleの制御をしたい。
- 各APIの使用条件は複数のRoleの組み合わせ
- アクションクラスは1つにまとめたい
というわけで引数付きのアクションアノテーションで実装してみた。
とりあえずRoleを適当に定義
ユーザ、管理者、システム、なしの4つのRoleがあるとする。
Roles.java
public enum Roles {
USER((short)0), // ユーザ
ADMINISRATOR((short)1), // 管理者
SYSTEM((short)2), // システム
NONE((short)99); // なし
private short id;
Roles(short id) {
this.id = id;
}
public Short getId() { return id; }
}
アクションアノテーションを作成する
引数で受け取ったRoleをユーザが持っているかチェックし、持っていなければ403を返し、
持っていたら元のActionへ返す処理を適当に書く。
AuthRoleAction.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.With;
import play.mvc.Http.Context;
import play.mvc.Result;
@With(AuthRoleAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface AuthRole {
Roles[] value() default Roles.NONE;
}
public class AuthRoleAction extends Action<AuthRole> {
@Override
public Promise<Result> call(Context ctx) throws Throwable {
// 引数で許可されるRoleを受け取る
Roles[] roles = configuration.value();
// サインインユーザのRole情報と引数で渡されたRoleのチェック
Boolean authResult = isAuthorizedRole(roles);
if(authResult)
{
// 権限OK
return delegate.call(ctx);
}
else
{
// 権限NG
return F.Promise.pure((Result) unauthorized());
}
}
}
Actionにアクションアノテーションを付ける
Controllerの各アクションに、許可するRoleを引数にして@AuthRoleアノテーションを付加する。
Controller.java
public class TestAuthController extends Controller{
// 使用していいRoleを渡す
@AuthRole({Roles.USER, Roles.ADMINISRATOR})
public static Result test() {
return ok();
}
}