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}