    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.resource;
    017
    018import java.text.MessageFormat;
    019import java.util.List;
    020
    021import org.opengion.hayabusa.common.HybsSystem;
    022import org.opengion.hayabusa.common.HybsSystemException;
    023import org.opengion.hayabusa.common.SystemManager;
    024import org.opengion.fukurou.util.LogWriter;
    025import org.opengion.fukurou.util.Cleanable;
    026import org.opengion.fukurou.util.StringUtil;
    027import org.opengion.fukurou.util.ApplicationInfo;
    028import org.opengion.fukurou.db.DBUtil;
    029
    030/**
    031 * systemId に対応したユーザー情報を作成するファクトリクラスです。
    032 *
    033 * UserInfoオブジェクトは，キャッシュせずに、要求都度、データベースを検索します。
    034 * これは、ユーザー登録が、他システムより行われる可能性を考慮している為です。
    035 * ユーザーオブジェクトの要求は、基本的にログイン時のみで、その後セッションに
    036 * キープされます。
    037 *
    038 * 検索するカラムには、必ず、USERID,LANG,NAME,ROLES,DROLES がこの順番で含まれており、
    039 * 絞込み条件(?パラメータ)として、SYSTEM_ID,USERID がこの順番で指定される必要があります。
    040 * (カラム名は関係ありません。並び順と意味が重要です。)
    041 * また、検索順(ORDER BY)は、優先順位の低い順に検索してください。使用するのは、一番最後に
    042 * 検索された行を使用します。
    043 * ユーザーリソースは、RESOURCE_USER_DBID で指定のデータベースから取得します。
    044 * 未定義の場合は、RESOURCE_DBID から、それも未定義の場合は デフォルトの接続先を
    045 * 使用します。
    046 *
    047 * SYSTEM_ID='**' は、共通リソースです(ROLESも共通に設定する必要があります。)。
    048 * これは、システム間で共通に使用されるリソース情報を登録しておきます。
    049 * SYSTEM_ID は、指定のシステムIDと**を検索対象にします。**は、全システム共通の
    050 * 指定のシステムIDと**と両方存在する場合は、指定のシステムIDが優先されます。
    051 *
    052 * ver4 では、デフォルトロールという考え方がなくなりましたので、画面のロールに、
    053 * (*)を明示的に追加し、RWMODE を指定する必要があります。
    054 *
    055 * @og.rev 4.0.0.0 (2004/12/31) 新規作成
    056 * @og.group リソース管理
    057 *
    058 * @version  4.0
    059 * @author   Kazuhiko Hasegawa
    060 * @since    JDK5.0,
    061 */
    062public final class UserInfoFactory {
    063
    064        private static final String SYSTEM_ID = HybsSystem.sys( "SYSTEM_ID" );
    065
    066        // ユーザーリソースの接続先を、取得します。
    067        private static String dbid = StringUtil.nval(
    068                                                                HybsSystem.sys( "RESOURCE_USER_DBID" ) ,
    069                                                                HybsSystem.sys( "RESOURCE_DBID" )
    070                                                        ) ;
    071
    072        // ユーザーリソースのキー指定読み込みのクエリー
    073        private static String query                     = HybsSystem.sys( "RESOURCE_USER_SQL" );
    074        private static String queryRole         = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" );
    075
    076        // 5.2.0.0 (2010/09/01) LDAP対応
    077        private static String srcType           = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" );
    078        private static String[] ldapClm         = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) );
    079        private static String ldapFilter        = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" );
    080        private static String ldapRoleFilter= HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" );
    081
    082        private static String searchScope       = HybsSystem.sys( "LDAP_SEARCH_SCOPE" );
    083        private static String initctx           = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" );
    084        private static String providerURL       = HybsSystem.sys( "LDAP_PROVIDER_URL" );
    085        private static String entrydn           = HybsSystem.sys( "LDAP_ENTRYDN" );
    086        private static String password          = HybsSystem.sys( "LDAP_PASSWORD" );
    087        private static String searchbase        = HybsSystem.sys( "LDAP_SEARCH_BASE" );
    088
    089        /** コネクションにアプリケーション情報を追記するかどうか指定 */
    090        public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
    091
    092        // 4.0.0 (2005/01/31) Cleanable インターフェースによる初期化処理
    093        static {
    094                Cleanable clr = new Cleanable() {
    095                        public void clear() {
    096                                UserInfoFactory.clear();
    097                        }
    098                };
    099
    100                SystemManager.addCleanable( clr );
    101        }
    102
    103        private static final Object lock = new Object();
    104
    105        /**
    106         *  デフォルトコンストラクターをprivateにして、
    107         *  オブジェクトの生成をさせないようにする。
    108         *
    109         */
    110        private UserInfoFactory() {
    111        }
    112
    113        /**
    114         * UserInfo オブジェクトを取得します。
    115         *
    116         * UserInfoオブジェクトは，キャッシュせずに、要求都度、データベースを検索します。
    117         * これは、ユーザー登録が、他システムより行われる可能性を考慮している為です。
    118         * ユーザーオブジェクトの要求は、基本的にログイン時のみで、その後セッションに
    119         * キープされます。
    120         *
    121         * @og.rev 3.7.0.4 (2005/03/18) ゲストログイン機能追加
    122         * @og.rev 4.0.0.0 (2007/10/31) ロール指定でのログイン機能追加
    123         * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグへの対応
    124         * @og.rev 4.4.0.0 (2009/08/02) データロール対応
    125         * @og.rev 5.2.0.0 (2010/09/01) LDAP対応
    126         * @og.rev 5.3.6.0 (2011/06/01) GE20の読み込みをUserInfo内に移動
    127         * @og.rev 5.10.16.2 (2019/10/28) X-Forwarded-For対応
    128         *
    129         * @param       userID          ユーザーID
    130         * @param       ipAddress       ログイン端末のIPアドレス
    131         * @param       roles           データロール
    132         * @param  xFwdFor              X-FORWARDED-FOR
    133         *
    134         * @return      UserInfoオブジェクト
    135         */
    136//      public static UserInfo newInstance( final String userID,final String ipAddress,final String roles ) {
    137        public static UserInfo newInstance( final String userID,final String ipAddress,final String roles, final String xFwdFor ) {
    138                String[] xfwd = StringUtil.csv2ArrayOnly(xFwdFor);
    139                String xfwdFst = xfwd.length ==0 ? null : xfwd[0];
    140                String clientIP = StringUtil.nval( xfwdFst , ipAddress );// 5.10.16.2　xFWDForがセットされている場合はIPアドレスの代わりにそちらを利用
    141
    142                // 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    143                ApplicationInfo appInfo = null ;
    144                if( USE_DB_APPLICATION_INFO ) {
    145                        appInfo = new ApplicationInfo();
    146                        // ユーザーID,IPアドレス,ホスト名
    147//                      appInfo.setClientInfo( userID,ipAddress,null );
    148                        appInfo.setClientInfo( userID,clientIP,null ); // 5.10.16.2 (2019/10/28)
    149                        // 画面ID,操作,プログラムID
    150                        appInfo.setModuleInfo( "UserInfoFactory",null,"newInstance" );
    151                }
    152
    153//              String[] args;
    154//              String[][] vals;
    155
    156//              if( roles == null || roles.length() == 0 ) {
    157//                      args = new String[] { SYSTEM_ID,userID };
    158//                      synchronized( lock ) {
    159//                              vals = DBUtil.dbExecute( query,args,appInfo,dbid );
    160//                      }
    161//              }
    162//              // 4.0.0.0 (2007/10/31)
    163//              else {
    164//                      args = new String[] { SYSTEM_ID,userID,roles };
    165//                      synchronized( lock ) {
    166//                              vals = DBUtil.dbExecute( queryRole,args,appInfo,dbid );
    167//                      }
    168//              }
    169
    170                String[][] vals;
    171                if( "LDAP".equalsIgnoreCase( srcType ) ) {
    172                        vals = getValsByLdap( userID, roles );
    173                }
    174                else {
    175                        vals = getVals( userID, roles, appInfo );
    176                }
    177
    178                final UserInfo info ;
    179                int len = vals.length ; // システムID ** を含む。
    180                if( len >= 1 && vals[0].length >= 5 ) {
    181                        // システムIDでソートされる。SYSTEM_ID="**"は最初に現れるので、最後を取得
    182                        info = new UserInfo(
    183                                                                userID          ,                       // userID
    184                                                                vals[len-1][1]  ,               // lang
    185                                                                vals[len-1][2]  ,               // jname
    186                                                                vals[len-1][3]  ,               // roles
    187                                                                vals[len-1][4]  ,               // droles // 4.4.0.0 (2009/08/02)
    188                                                                SYSTEM_ID               ,               // systemId
    189                                                                ipAddress               ,               // ipAddress
    190                                                                appInfo                 ,               // ApplicationInfo
    191                                                                clientIP                                // 5.10.16.2 (2019/10/28)
    192                                                                ) ;
    193                }
    194                else {
    195                        String errMsg = "UserInfo のデータ(USERID,LANG,NAME,ROLES,DROLES)が取得できません。"
    196                                                + " Key [" + userID + "]"
    197                                                + " SQL [" + query + "]" ;
    198                        LogWriter.log( errMsg );
    199                        throw new HybsSystemException( errMsg );
    200                }
    201
    202                return info ;
    203        }
    204
    205        /**
    206         * UserInfoFactoryをクリアします。
    207         *
    208         * @og.rev 5.2.0.0 (2010/09/01) LDAP対応
    209         *
    210         */
    211        public static void clear() {
    212                synchronized( lock ) {
    213                        dbid = StringUtil.nval(
    214                                                                        HybsSystem.sys( "RESOURCE_USER_DBID" ) ,
    215                                                                        HybsSystem.sys( "RESOURCE_DBID" )
    216                                                                ) ;
    217                        query = HybsSystem.sys( "RESOURCE_USER_SQL" );
    218                        queryRole = HybsSystem.sys( "RESOURCE_USER_ROLE_SQL" );
    219
    220                        // 5.2.0.0 (2010/09/01) LDAP対応
    221                        srcType                 = HybsSystem.sys( "RESOURCE_USER_SRC_TYPE" );
    222                        ldapClm                 = StringUtil.csv2Array( HybsSystem.sys( "RESOURCE_USER_LDAP_CLM" ) );
    223                        ldapFilter              = HybsSystem.sys( "RESOURCE_USER_LDAP_FILTER" );
    224                        ldapRoleFilter  = HybsSystem.sys( "RESOURCE_USER_ROLE_LDAP_FILTER" );
    225
    226                        searchScope             = HybsSystem.sys( "LDAP_SEARCH_SCOPE" );
    227                        initctx                 = HybsSystem.sys( "LDAP_INITIAL_CONTEXT_FACTORY" );
    228                        providerURL     = HybsSystem.sys( "LDAP_PROVIDER_URL" );
    229                        entrydn                 = HybsSystem.sys( "LDAP_ENTRYDN" );
    230                        password                = HybsSystem.sys( "LDAP_PASSWORD" );
    231                        searchbase              = HybsSystem.sys( "LDAP_SEARCH_BASE" );
    232                }
    233        }
    234
    235        /**
    236         * DBからユーザーリソースの情報を取得します。
    237         *
    238         * @og.rev 5.2.0.0 (2010/09/01) 新規作成
    239         *
    240         * @param       userId  ユーザーID
    241         * @param       roles   ロール
    242         * @param       appInfo DB接続情報
    243         *
    244         * @return ユーザーリソース情報
    245         */
    246        private static String[][] getVals( final String userId, final String roles, final ApplicationInfo appInfo ) {
    247                String[] args;
    248                String[][] rtn = null;
    249
    250                if( roles == null || roles.length() == 0 ) {
    251                        args = new String[] { SYSTEM_ID,userId };
    252                        synchronized( lock ) {
    253                                rtn = DBUtil.dbExecute( query,args,appInfo,dbid );
    254                        }
    255                }
    256                // 4.0.0.0 (2007/10/31)
    257                else {
    258                        args = new String[] { SYSTEM_ID,userId,roles };
    259                        synchronized( lock ) {
    260                                rtn = DBUtil.dbExecute( queryRole,args,appInfo,dbid );
    261                        }
    262                }
    263
    264                return rtn;
    265        }
    266
    267        /**
    268         * LDAPからユーザーリソースの情報を取得します。
    269         *
    270         * @og.rev 5.2.0.0 (2010/09/01) 新規作成
    271         *
    272         * @param       userId  ユーザーID
    273         * @param       roles   ロール
    274         *
    275         * @return ユーザーリソース情報
    276         */
    277        private static String[][] getValsByLdap( final String userId, final String roles ) {
    278                LDAPSearch serch = new LDAPSearch();
    279                serch.setSearchScope( searchScope ) ;
    280                serch.setInitctx( initctx ) ;
    281                serch.setProviderURL( providerURL ) ;
    282                serch.setSearchbase( searchbase ) ;
    283                if( entrydn != null  ) { serch.setEntrydn( entrydn ) ; }
    284                if( password != null ) { serch.setPassword( password ) ; }
    285                serch.setAttributes( ldapClm ) ;
    286                serch.init();
    287
    288                String filter = ( roles == null || roles.length() == 0 ) ? ldapFilter : ldapRoleFilter;
    289                String[] args = ( roles == null || roles.length() == 0 ) ? new String[] { SYSTEM_ID,userId } : new String[] { SYSTEM_ID,userId,roles };
    290                filter = MessageFormat.format( filter,(Object[])args );
    291
    292                List<String[]> list = serch.search( filter );
    293
    294                String[][] rtn = null;
    295                if( list.size() > 0 ) {
    296                        rtn = new String[1][];
    297                        rtn[0] = list.get( 0 );
    298                        rtn[0][1] = StringUtil.nval( rtn[0][1], "ja" );                 // 言語のデフォルト値は、'ja'
    299                        rtn[0][2] = StringUtil.nval( rtn[0][2], rtn[0][0] );    // 名称のデフォルト値は、ユーザーID
    300                        rtn[0][3] = StringUtil.nval( rtn[0][3], ldapClm[3] );   // ロールズの初期値は、ロールに設定された項目名
    301                        rtn[0][4] = StringUtil.nval( rtn[0][4], "" );
    302                }
    303
    304                return rtn;
    305        }
    306}