intra-mart Accel Platform 認可仕様書 第12版 2017-08-01

サブジェクト管理

ここでは認可情報のサブジェクト管理系の機能について、個別に解説します。

サブジェクトとサブジェクトグループ

サブジェクト

サブジェクトは認可対象者を示す情報です。ただしこれは「特定の誰か」に限らず、ユーザの所属できる組織やロールなどを含みます。ユーザが複数の組織やロールに所属していれば複数のサブジェクトとして解釈されます。

サブジェクトはどのような種類のものであるかにかかわりなく認可機構内でユニークなサブジェクトIDとして管理されます。

サブジェクトグループ

認可機構で権限の付与を行う際、サブジェクトをグループ化した単位で設定を行います。グルーピングには条件指定が可能であり、以下の演算をサポートしています。

OR
含まれるサブジェクトのいずれかにマッチした場合のみ、そのサブジェクトグループに属すると判断されます。
AND
含まれるサブジェクトのすべてにマッチした場合のみ、そのサブジェクトグループに属すると判断されます。
NOT
一致するサブジェクト、またはサブジェクトグループに含まれる場合、そのサブジェクトグループに属さないと判断されます。

たとえば、以下のようなグループを条件として構成することができます。

-  開発部 AND 課長
-  総務部 AND NOT( 協力会社員グループ )
-  ( 開発部 OR 営業部 OR 企画部 ) AND ( NOT 協力会社員グループ )

サブジェクトグループカテゴリ

サブジェクトグループカテゴリはAPIが自動生成する情報です。サブジェクトマネージャを使用して新たなサブジェクトグループを登録すると、サブジェクトグループ内で使用されているサブジェクトタイプを取り出し、そのサブジェクトタイプをもとにサブジェクトグループカテゴリを生成します。

カテゴリの生成にかかわる仕様は以下の通りです。

  • グループ内に存在するサブジェクトタイプを収集
  • 収集したサブジェクトタイプをもとに以下を決定します。
    • サブジェクトグループカテゴリIDの決定
      • サブジェクトタイプが3種以上の場合 (dummy) のハッシュ値をカテゴリIDとして使用
      • サブジェクトタイプが2種の場合、 : をデリミタとしてサブジェクトタイプIDを連結した文字列のハッシュ値をカテゴリIDとして使用
      • サブジェクトタイプが1種の場合、 サブジェクトタイプIDのハッシュ値をカテゴリIDとして使用
    • サブジェクトグループカテゴリ名の決定(上記IDがすでにテーブルに存在する場合それを使用)
      • サブジェクトタイプが3種以上の場合 「その他複合」
      • サブジェクトタイプが2種の場合、 「サブジェクトタイプA、サブジェクトタイプBの複合」
      • サブジェクトタイプが1種の場合、 サブジェクトタイプ名をそのまま使用

サブジェクトタイプ

サブジェクトタイプは認可機構のサブジェクトとサブジェクトの実体の情報を相互にやり取りするための仕組みです。サブジェクトは必ずいずれかのサブジェクトタイプに属し、サブジェクトタイプを通してサブジェクトの実体情報との相互変換ができます。

たとえば IM共通マスタ では会社組織、役職、パブリックグループ、役割といったサブジェクトタイプを用意しています。そのため認可機構でこれらの情報をサブジェクトとして取り扱うことができます。

サブジェクトタイプは SubjectType インタフェースを実装するJavaクラスで定義されます。このクラスの追う責務は以下のようなものです。

  • サブジェクトタイプのID、名称を決定する
  • サブジェクトIDと実体の情報を紐づける
  • サブジェクトの実体の情報の式表現へ直列化、および、復元を行う

サブジェクトタイプの定義

サブジェクトタイプは必要に応じて、実装を追加することができます。サブジェクトタイプを定義するためには SubjectType インタフェースを実装したクラスと、サブジェクトを扱うためのモデルクラスを作成する必要があります。

サブジェクトタイプは以下のクラスを実装します。

完全修飾クラス名
jp.co.intra_mart.foundation.authz.model.subjects.SubjectType<T>

型引数Tはサブジェクトのモデルクラスです。このモデルクラスには特に制約はありません。ここで定義したモデルクラスを使用してサブジェクト登録を行ったりすることができるようになるので、役割として適切であればアプリケーションなどで使用している既存のクラスをそのまま使用したほうが取り扱い易くなるでしょう。

注意

SubjectTypeとサブジェクトモデルクラスは1対1の関係で定義されている必要があります。他のサブジェクトタイプとモデルを共有することはできないので注意してください。

上記で定義したクラスは設定ファイルに記載することで認可機構に認識させます。以下のXMLファイルを作成します。

場所
%CONTEXT_PATH%/WEB-INF/conf/authz-subject-type-config/ 配下
XMLスキーマ
%CONTEXT_PATH%/WEB-INF/schema/authz-subject-type-config.xsd

下記は設定例です。下記のように、 subject-type 要素type-class 属性 にサブジェクトタイプの実装クラスを、 model-class 属性 にモデルクラスを、それぞれ完全修飾クラス名で記述します。

<?xml version="1.0" encoding="UTF-8"?>
<p:authz-subject-type-config
    xmlns:p="http://www.intra-mart.jp/authz/authz-subject-type-config/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.intra-mart.jp/authz/authz-subject-type-config/ ../../schema/authz-subject-type-config.xsd">

  <subject-type
      type-class="jp.co.intra_mart.foundation.authz.subjecttype.im_master.ImRole"
      model-class="jp.co.intra_mart.foundation.admin.role.model.RoleInfo" />

</p:authz-subject-type-config>

サブジェクトタイプの追加にあたっては別途 「認可拡張プログラミングガイド」の「サブジェクト拡張ガイド」の章 で手順や必要な準備について解説しています。サブジェクトタイプを追加する際には、上記の資料もあわせて参照してください。

intra-mart Accel Platform の標準的なモジュール構成においてデフォルトでインストールされる サブジェクトタイプの詳細については「intra-mart Accel Platform に含まれるサブジェクトタイプ 」を参照してください。

基準日によって名称が変わるサブジェクトタイプ

期間情報を持ち、基準日によって名称が変わる場合は、SubjectType インタフェースを内包する ChangeableNameSubjectType インタフェースを利用できます。
ChangeableNameSubjectType インタフェースを利用したサブジェクトタイプの場合、「認可設定」画面で対象者条件を設定する際に基準日に応じた名称を表示します。
ChangeableNameSubjectType は名称の解決に基準日を使用するメソッドを提供します。 それ以外は SubjectType と同じです。
完全修飾クラス名
jp.co.intra_mart.foundation.authz.model.subjects.ChangeableNameSubjectType<T>

コラム

ChangeableNameSubjectType インタフェースは intra-mart Accel Platform 2013 Winter から提供しています。

API

サブジェクト管理に関係する主要なAPI上の操作を説明します。詳細に関してはAPIリストを参照してください。

マネージャインスタンスの取得

サブジェクト管理の主要な操作を行うためには SubjectManager クラスを使用します。
マネージャクラス、および、ファクトリクラスは以下の通りです。
マネージャクラス
jp.co.intra_mart.foundation.authz.services.admin.SubjectManager
マネージャファクトリ
jp.co.intra_mart.foundation.authz.services.admin.SubjectManagerFactory

マネージャインスタンスはファクトリクラスを使用して取得します。ファクトリも自身のファクトリメソッドを持っていますので、以下のようにして取得します。

// マネージャインスタンスの取得
final SubjectManager subjectManager = SubjectManagerFactory.getInstance().getSubjectManager();

APIを利用したサブジェクトの管理

サブジェクトの登録

特定サブジェクトタイプの主キー文字列からサブジェクトを登録する場合は以下のようにします。IM共通マスタ のユーザ aoyagi をサブジェクトとして登録する例です。

// サブジェクトタイプIDと、主キー情報を与えてサブジェクトを登録
// キー情報の与え方はサブジェクトタイプの定義によります
final SubjectManager subjectManager = SubjectManagerFactory.getInstance().getSubjectManager();
Subject aoyagiSubject = subjectManager.registerAsSubject("imm_user", "aoyagi");

サブジェクトタイプに定義されるモデルクラスを使ってサブジェクトを登録することもできます。この定義は

%CONTEXT_PATH%/WEB-INF/conf/authz-subject-type-config

に格納されているxmlファイルで定義されています。

IM共通マスタ「ユーザ」の場合の実装例は、以下の通りです。

// IM共通マスタのUserManagerを利用してユーザのモデルを取得
UserManager userManager = new UserManager();
IUserBizKey bizKey = new UserBizKey();
bizKey.setUserCd("aoyagi");
User user = userManager.getUser(bizKey, new Date());

// ユーザのモデルからサブジェクト登録
Subject aoyagiSubject = subjectManager.registerAsSubject(user);

SubjectManager#registerAsSubject() は既に登録されているサブジェクトを再度登録しようとした場合、同じ物を返します。(エラーに成りません)

サブジェクトグループの登録

サブジェクトの条件式を登録する場合はサブジェクトをベースに式からサブジェクトグループを作成します。上記までで青柳のサブジェクトを作成した前提で、「青柳または上田」のサブジェクト条件を作成する例です。

// サブジェクトグループに付加する名称(日本語のみ)を作成します
I18nValue<String> name = new I18nValue(Locale.JAPANESE, "上田または青柳");
// サブジェクトグループに付加する説明(日本語のみ)を作成します
I18nValue<String> desc = new I18nValue(Locale.JAPANESE, "上田または青柳です");

// 上田のサブジェクトを登録
Subject uedaSubject = subjectManager.registerAsSubject("imm_user", "ueda");

// OR(S(imm_user:aoyagi),S(imm_user:ueda)) の APIでの記述
Expression e = SubjectExpression.OR(SubjectExpression.S(aoyagiSubject), SubjectExpression.S(uedaSubject));
// 条件式をサブジェクトグループとして登録
SubjectGroup group = subjectManager.registerSubjectGroup(e, name, desc);

サブジェクトグループの取得

式かサブジェクトグループIDでの取得を行えます。存在しない場合、nullが返却されます。

// サブジェクトグループIDによる取得
SubjectGroup groupA = subjectManager.getSubjectGroup(group.getSubjectGroupId())

// 式による取得
Expression e = SubjectExpression.OR(SubjectExpression.S(aoyagiSubject), SubjectExpression.S(uedaSubject));
SubjectGroup groupB = subjectManager.getSubjectGroupByExpression(e);

サブジェクトグループの名称、説明の更新

サブジェクトグループの名称や説明を更新する場合は個別にマネージャのメソッドをコールします。

// サブジェクトグループに付加する名称(日英)
final I18nValue<String> name = new I18nValue(Locale.JAPANESE, "上田または青柳");
name.put(Locale.ENGLISH, "ueda or aoyagi");

// 名前の更新
subjectManager.setSubjectGroupNames(subjectGroupId, name);

// サブジェクトグループに付加する説明(日英)
final I18nValue<String> desc = new I18nValue(Locale.JAPANESE, "上田または青柳です");
desc.put(Locale.ENGLISH, "aoyagi or ueda");

// 説明の更新
subjectManager.setSubjectGroupDescriptions(subjectGroupId, desc);

サブジェクトグループの削除

サブジェクトグループを削除すると、関係するサブジェクトが他のサブジェクトグループから参照されていなければ同時に削除します。

// サブジェクトグループを削除
subjectManager.removeSubjectGroup(group);

式表現

式の文字列表現

サブジェクトグループは文字列化した式表現を持っています。IM共通マスタ「ユーザ」で aoyagi を示す場合の例は、以下の通りです。

S(imm_user:aoyagi)

S( ... ) はサブジェクトを表す式であり、imm_user はこのサブジェクトのサブジェクトタイプを示しています。: より右はこのサブジェクトタイプによって定義される識別子で、どういう書式で何を意味するかはサブジェクトタイプが決定します。

この例の場合、imm_user は IM共通マスタ が用意しているユーザマスタのサブジェクトタイプIDです。: の右側の aoyagi はこのサブジェクトタイプの定義するキー情報です。この場合は、 aoyagi というユーザコードを意味しています。

また、論理演算子として OR AND NOT が使用できます。

演算子 説明
S サブジェクトを表す式。括弧内には subject-type-id:subject-id-string の形式でサブジェクトを識別可能な文字列を指定します。このsubject-id-stringの書式はサブジェクトタイプによって定義されます。評価対象がこの文字列によって定義されるサブジェクトに一致する場合のみ真を返します
OR 括弧内に複数の式を記述でき、評価対象がいずれかの式に一致する場合真を返します
AND 括弧内に複数の式を記述でき、評価対象が全ての式に一致する場合真を返します
NOT 括弧内に単一の式のみ記述できます。評価対象が一致しない場合に真を返します

これらを使用した式の書式は、以下の通りです。

式:演算子( 式  | 式 [,式] ... )

ユーザコード aoyagi または ueda を示す場合の例は、以下の通りです。

OR(S(imm_user:aoyagi),S(imm_user:ueda))

式クラス表現

式は以下のクラスで表現されます。

../../../_images/ExpClass.png
  • 各演算子毎のExpressionクラスが定義されています。

  • AndExpクラス , OrExpクラス は複数の式を内包できます。それぞれ文字列表現における OR()AND() に対応します。

  • NotExpクラス が内包することができるのは単一の式のみです。文字列表現における NOT() に対応します。

  • SubjectExpressionクラス サブジェクトを表現する演算子です。文字列表現における S() に対応します。
    式の文字列表現 で述べている通り、この式の内容はサブジェクトタイプによって定義されます。

実際にこれらのクラスを使用して式のインスタンスを構築すると以下のような構造を取ります。

../../../_images/ExpInstance.png
  • AndExpクラス , OrExpクラス , NotExpクラス は 別の式のインスタンスを内包できるため、階層的な構造をとります。
  • SubjectExpressionクラス は必ず末端に記述します。逆にそれ以外の演算子が末端の式に現れることはありません。

式のマッチング仕様

登録されたサブジェクトグループ群に対して、ユーザがサブジェクトグループにマッチするかどうか評価する必要があります。ユーザがどのサブジェクトグループに当たるかの判定はサブジェクト解決系の処理が起点となって行います。サブジェクト解決処理の概要については「サブジェクト解決系 」を参照してください。

サブジェクト解決系の処理の中では、以下の2段階で処理を行っています。

  1. 認可サブジェクトコンテキストまたはサブジェクトリゾルバを使用してユーザのサブジェクトを解決し
  2. 解決されたサブジェクトからサブジェクト管理に登録されているサブジェクトグループ(条件)のどれにマッチするかを判断する

ここでは上記 2 でユーザの該当するサブジェクトが解決された状態で式とのマッチングをどのように行っているかを説明します。

まず、ユーザの該当するサブジェクトから、合致する可能性のあるサブジェクトグループ(条件式)を探します。これは単純にユーザのサブジェクトを使用したサブジェクトグループであるかどうかを条件にデータベース上から取得し、式オブジェクト( Expression クラスのインスタンス)を構築します。

マッチングにはExpressionクラスと同様の構成をもつMatcherクラスを使用します。以下はマッチングに使用される主要なクラスです。

../../../_images/MatcherClass.png

Matcher クラスはそれぞれ Expression クラスに対応する形で定義されています。Matcher クラスと Expression クラスの関係を下図に示します。

../../../_images/ExpMatcherRel.png
  1. Expression クラスの getMatcher() メソッドは Expression クラスの実行時型に対応するMatcher クラスのインスタンスを返します。
  2. このインスタンスは生成元の Expression インスタンスを保持しており、 test() メソッドがコールされると生成元 Expression インスタンスから、内包している Expression インスタンスを取り出し
  3. 取り出した Expression インスタンスそれぞれに対して getMatcher() を行い
  4. 取得したMatcherインスタンスの test() メソッドをコールします。これは再帰的に処理され、最終的に末端である SubjectExpression クラスのインスタンスまで実行されます。
  5. SubjectMatcher は引数に与えられた Subject が自分の対応する Expression に一致するかどうかをチェックし、マッチしたかどうかの結果を上位の式の Matcher に返します。
  6. この結果は順に上位の式に集約され、最終的に最上位の式の Matcher まで戻ります。
  7. 最上位の Matcher が最後の評価を行い、マッチしたかどうかの結果を返します。

省略処理

式は以下のような観点での省略処理をします。

  • 無駄なネストの排除
  • オペランドのソート

演算子によって以下のように省略処理を行います。

ANDの場合

  1. オペランドを順に省略処理する(再起処理)
  2. オペランドが AND 演算子を使用( AND のネスト)している場合、オペランドの AND を外す
  • 例) AND( a, b, AND( c, d) )AND( a, b, c, d )
  1. オペランドの重複を排除
  • 例) AND( a, b, a, b )AND( a, b )
  1. オペランドをソート
  • 例) AND( a, b, d, c )AND( d, c, b, a )

ORの場合

  1. オペランドを順に省略処理する(再起処理)
  2. オペランドが OR 演算子を使用( OR のネスト)している場合、オペランドの OR を外す
  • 例) OR( a, b, OR( c, d) )OR( a, b, c, d )
  1. オペランドの重複を排除
  • 例) OR( a, b, a, b )OR( a, b )
  1. オペランドをソート
  • 例) OR( a, b, d, c )OR( d, c, b, a )

NOTの場合

  1. オペランドを省略処理する(再起処理)
  2. オペランドがNOT演算子を使用している場合、自身とオペランドの NOT を打ち消す。
  • 例) NOT(NOT(A))A

ERとテーブル上の表現

サブジェクト管理に関係するテーブルの ER は以下の通りです。

../../../_images/ER_Subject.png

ここでは API 上のモデルと ER 上の関連を中心に説明します。テーブルの定義や認可機構全体の ER については別冊のテーブル定義書、 ER 図を参照してください。

サブジェクト(imaz_subject)

主要なフィールド
論理名 物理名
サブジェクトID sid
サブジェクトタイプ subject_type

サブジェクトが追加・削除されたタイミングでレコードも追加削除されます。サブジェクトIDはサブジェクトタイプとサブジェクトの実体のキーの値をもとに生成したハッシュ値です。このため、サブジェクトテーブルのレコードに対して更新は原則発生しません。

サブジェクトテーブルは、サブジェクトIDのマスタ情報ですが、サブジェクトIDが紐づけられた実体の情報はサブジェクトタイプクラスを通して引き当てる必要があります。

サブジェクトグループ所属(imaz_subject_group_ath)

主要なフィールド
論理名 物理名
サブジェクトID sid
サブジェクトグループID subject_group_id
単項演算子 monadic_operator

単純にサブジェクトグループとサブジェクトを紐づけます。サブジェクトグループの構成の中にサブジェクトも含まれるため、サブジェクトグループを登録する際にこのテーブルのレコードも追加されます。 単項演算子フィールドは NOT 接続かどうかを示します。

たとえば AND(S(X)) のような式の場合に、AND がサブジェクトグループ、S(X) がサブジェクトとして登録され、その関係をこのサブジェクトグループ所属テーブルが保持します。ADN(NOT(S(X))) のような式の場合、間に NOT が入っているので、単項演算子の値に NOT を示す値 が入ります。

サブジェクトグループ(imaz_subject_group)

主要なフィールド
論理名 物理名
サブジェクトグループID subject_group_id
論理演算子 logical_operator
expression

サブジェクトグループを保持します。サブジェクトグループは内部的には式表現における AND または OR と同等の構造を表し、式のインスタンス同様、ツリー構造で表します。サブジェクトグループIDは式表現を省略処理した上でハッシュ化した値をもとに生成されるため、式が変更されると別のサブジェクトグループIDに変わります。一度登録されたサブジェクトグループに対して更新が発生することは原則ありません(名称、説明を除き)。

式構造はサブジェクトグループの階層として表現されます。このため式フィールドは登録時メモとして保持していますが、実際に式の復元に使用されません。

サブジェクトグループ国際化(imaz_subject_group_i)

主要なフィールド
論理名 物理名
サブジェクトグループID subject_group_id
ロケールID locale_id
表示名 display_name
説明 description

サブジェクトグループについて名称と説明を保持します。双方、各ロケールことに保持することができます。

サブジェクトグループ構造(imaz_subject_group_struct)

主要なフィールド
論理名 物理名
親グループID parent_group_id
子グループID child_group_id
単項演算子 monadic_operator

サブジェクトグループ間の直接の親子関係を保持します。サブジェクトグループの階層構造は、条件の式表現を反映したものです。ネストした式を表現するためにある式とその式が内包する式との関係を表しています。

このテーブルもサブジェクトグループ所属テーブル同様、NOT接続のために単項演算子フィールドがあります。

サブジェクトグループメンバ(imaz_subject_group_member)

主要なフィールド
論理名 物理名
トップグループID top_group_id
メンバーグループID member_group_id
距離 distance

このテーブルはサブジェクトグループ構造テーブルの参照を高速化するための情報を保持します。APIからサブジェクトグループ登録処理を呼び出した際に、作成されるサブジェクトグループのツリー構造における先頭ノードと各構成ノードの関連を保持します。リソースグループ内包テーブルのように各要素間の情報を保持しているわけではありません。

サブジェクトグループカテゴリ(imaz_subject_group_cat)

主要なフィールド
論理名 物理名
カテゴリID category_id
ソートキー sort_key

サブジェクトグループカテゴリはAPIが自動生成する情報です。このテーブルの情報の生成に関する詳細は「サブジェクトグループカテゴリ 」を参照してください。

カテゴリIDはサブジェクトグループが含むサブジェクトタイプIDのハッシュ値をもとに生成されます。ソートキーを更新することができます。

サブジェクトグループカテゴリ国際化(imaz_subject_group_cat_i)

主要なフィールド
論理名 物理名
カテゴリID category_id
ロケールID locale_id
表示名 display_name

サブジェクトグループカテゴリの国際化情報を保持します。この情報はサブジェクトグループカテゴリを生成するタイミングで自動的に作成されます。( サブジェクトグループカテゴリ 参照 )この国際化情報はサブジェクトタイプの国際化情報と、デリミタなどの国際化情報を使用して、テナントで有効になっているロケール分だけ生成します。

サブジェクトグループカテゴリ所属(imaz_subject_group_cat_ath)

主要なフィールド
論理名 物理名
サブジェクトグループID subject_group_id
カテゴリID category_id
ソートキー sort_key

サブジェクトグループの所属するサブジェクトカテゴリの情報を保持します。サブジェクトグループの情報をもとにサブジェクトグループカテゴリが自動的に生成されるので、同時に作成されます。( サブジェクトグループカテゴリ 参照 )サブジェクトグループカテゴリ毎にサブジェクトグループのソートキーを保持します。