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 */
016 package org.opengion.hayabusa.filter;
017
018 import org.opengion.hayabusa.common.HybsSystem;
019
020 import java.io.IOException;
021 import java.io.PrintWriter;
022
023 import javax.servlet.Filter;
024 import javax.servlet.FilterChain;
025 import javax.servlet.FilterConfig;
026 import javax.servlet.ServletContext;
027 import javax.servlet.ServletException;
028 import javax.servlet.ServletRequest;
029 import javax.servlet.ServletResponse;
030 import javax.servlet.RequestDispatcher;
031 import javax.servlet.http.HttpServletResponse;
032 import javax.servlet.http.HttpServletRequest;
033
034 import org.opengion.fukurou.security.URLHashMap;
035 import org.opengion.fukurou.util.StringUtil;
036 import org.opengion.fukurou.util.FileString;
037
038 /**
039 * URLHashFilter は、Filter インターフェースを継承した URLチェ?クラスです?
040 * web.xml で filter 設定することにより、??開始します?
041 * filter 処??、設定レベルとURLの飛?先により処?法が異なります?
042 * こ?フィルターでは、ハ?ュ?暗号化ではなく?アドレスに戻す作業になります?
043 * ?URLの場合?ハッシュ化?外部URLの場合?暗号化に適用されます?
044 *
045 * 基本?は、外部へのURLでエンジンシス?へ飛?す?合?、暗号化になります?
046 * ?へのURLは、基本?、パラメータのみ暗号化を行います?なお?直接画面ID?
047 * ?して飛?す?合を、止めるかど?は、設定レベルに依存します?
048 *
049 * フィルターの設定レベルは、シス?リソースの URL_ACCESS_SECURITY_LEVEL 変数で
050 * 設定します?
051 * なお??ベル共通で、戻し???レベルに関係なく実行されます?
052 * レベル?:なにも制限?ありません?
053 * レベル?:Referer チェ?を行います?つまり?URLを直接入力しても動作しません?
054 * ただし?Refererが付いてさえ?ば、アクセス許可を与えます?
055 * Referer 無し?場合でも?URLにパラメータが存在しな??また??
056 * アドレスがハ?ュ?暗号化されて?場合?、アクセスを許可します?
057 * レベル??場合?ハッシュ戻??化???行います?あくまで、ハ?ュ?
058 * 暗号化されて???合でも?Refererさえあれば、許可すると?ことです?
059 * (パラメータな?or ハッシュあり or Refererあり の場合?許可)
060 * レベル?:フィルター処?しては、レベル?と同じです?
061 * 異なる?は、URLのハッシュ?暗号化??、外部URLに対してのみ行います?
062 * (パラメータな?or ハッシュあり or Refererあり の場合?許可)
063 * レベル?:URLのパラメータがハ?ュ?暗号化されて??があります?
064 * レベル?同様?URLにパラメータが存在しな??合?、アクセスを許可します?
065 * レベル?と異なる?は、パラメータは?ハッシュ化か、暗号化されて?
066 * ?があると?ことです?(?/外部問わ?
067 * (パラメータな?or ハッシュあり の場合?許可)
068 * それ以外:アクセスを停止します?
069 *
070 * フィルターに対してweb.xml でパラメータを設定します?
071 * ・filename :停止時メ?ージ表示ファイル??/jsp/custom/refuseAccess.html)
072 * ・initPage :??にアクセスされる?期画面アドレス(初期値:/jsp/index.jsp)
073 * ・debug :??メ?ージの表示(初期値:false)
074 *
075 * 【WEB-INF/web.xml?
076 * <filter>
077 * <filter-name>URLHashFilter</filter-name>
078 * <filter-class>org.opengion.hayabusa.filter.URLHashFilter</filter-class>
079 * <init-param>
080 * <param-name>filename</param-name>
081 * <param-value>/jsp/custom/refuseAccess.html</param-value>
082 * </init-param>
083 * <init-param>
084 * <param-name>initPage</param-name>
085 * <param-value>/jsp/index.jsp</param-value>
086 * </init-param>
087 * <init-param>
088 * <param-name>debug</param-name>
089 * <param-value>false</param-value>
090 * </init-param>
091 * </filter>
092 *
093 * <filter-mapping>
094 * <filter-name>URLHashFilter</filter-name>
095 * <url-pattern>*.jsp</url-pattern>
096 * </filter-mapping>
097 *
098 * @og.group フィルター処?
099 *
100 * @og.rev 5.2.2.0 (2010/11/01) 新規追?
101 *
102 * @version 5.2.2.0 (2010/11/01)
103 * @author Kazuhiko Hasegawa
104 * @since JDK1.6,
105 */
106 public final class URLHashFilter implements Filter {
107 private static final String REQ_KEY = HybsSystem.URL_HASH_REQ_KEY ;
108
109 private static final int ACCS_LVL = HybsSystem.sysInt( "URL_ACCESS_SECURITY_LEVEL" );
110
111 private String initPage = "/jsp/index.jsp";
112 // private String filename = null; // アクセス拒否時メ?ージ表示ファイル?
113 private FileString refuseMsg = null; // アクセス拒否時メ?ージファイルの?(キャ?ュ)
114 private boolean isDebug = false;
115
116 /**
117 * フィルター処?体?メソ?です?
118 *
119 * @og.rev 5.3.0.0 (2010/12/01) ?化け対策として、setCharacterEncoding を実行する?
120 *
121 * @param request ServletRequestオブジェク?
122 * @param response ServletResponseオブジェク?
123 * @param chain FilterChainオブジェク?
124 * @throws IOException , ServletException
125 */
126 public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain ) throws IOException, ServletException {
127 HttpServletRequest req = (HttpServletRequest)request ;
128 req.setCharacterEncoding( "UTF-8" ); // 5.3.0.0 (2010/12/01)
129
130 if( isValidAccess( req ) ) {
131 String h_r = req.getParameter( REQ_KEY );
132 // ハッシュ化キーが存在する?
133 if( h_r != null ) {
134 HttpServletResponse resp = ((HttpServletResponse)response);
135 String qu = URLHashMap.getValue( h_r );
136 // キーに対する実アドレスが存在する?
137 if( qu != null ) {
138 String requestURI = req.getRequestURI(); // /gf/jsp/index.jsp など
139 String cntxPath = req.getContextPath(); // /gf など
140 // 自??身のコン?ストと同じなので、forward できる?
141 if( requestURI.startsWith( cntxPath ) ) {
142 String url = requestURI.substring(cntxPath.length()) + "?" + qu ;
143 RequestDispatcher rd = request.getRequestDispatcher( url );
144 rd.forward( request,response );
145 }
146 // そうでな??合?リ?レクトする?
147 else {
148 String url = resp.encodeRedirectURL( requestURI + "?" + qu );
149 resp.sendRedirect( url );
150 }
151 }
152 // キーに対する実アドレスが存在しな??(行き先無し?ケース)
153 else {
154 String url = resp.encodeRedirectURL( initPage );
155 resp.sendRedirect( url );
156 }
157 }
158 // ハッシュ化キーが存在しな??
159 else {
160 chain.doFilter(request, response);
161 }
162 }
163 else {
164 // アクセス拒否を示すメ?ージファイルの?を?力する?
165 response.setContentType( "text/html; charset=UTF-8" );
166 PrintWriter out = response.getWriter();
167 out.println( refuseMsg.getValue() );
168 out.flush();
169 }
170 }
171
172 /**
173 * フィルターの初期処?ソ?です?
174 *
175 * フィルターに対してweb.xml で初期パラメータを設定します?
176 * ・filename :停止時メ?ージ表示ファイル?
177 * ・initPage :??にアクセスされる?期画面アドレス(初期値:/jsp/index.jsp)
178 * ・debug :??メ?ージの表示(初期値:false)
179 *
180 * @param config FilterConfigオブジェク?
181 */
182 public void init( final FilterConfig config ) {
183 initPage = StringUtil.nval( config.getInitParameter("initPage"), initPage );
184 isDebug = StringUtil.nval( config.getInitParameter("debug") , isDebug );
185
186 ServletContext context = config.getServletContext();
187 String realPath = context.getRealPath( "/" );
188
189 // アクセス拒否を示すメ?ージファイルの?を管??FileString オブジェクトを構築する?
190 String filename = realPath + config.getInitParameter("filename");
191 refuseMsg = new FileString();
192 refuseMsg.setFilename( filename );
193 refuseMsg.setEncode( "UTF-8" );
194 }
195
196 /**
197 * フィルターの終???ソ?です?
198 *
199 */
200 public void destroy() {
201 // ここでは処?行いません?
202 }
203
204 /**
205 * フィルターの?状態をチェ?するメソ?です?
206 *
207 * 判定条件は、URL_ACCESS_SECURITY_LEVEL 変数 に応じて異なります?
208 * レベル?:なにも制限?ありません?
209 * レベル?:Referer チェ?を行います?つまり?URLを直接入力しても動作しません?
210 * レベル?:URLのハッシュ?暗号化??、外部URLに対してのみ行います?(チェ?は、レベル?と同?
211 * レベル?:URLのパラメータがハ?ュ?暗号化されて??があります?
212 * それ以外:アクセスを停止します?
213 *
214 * @param request HttpServletRequestオブジェク?
215 *
216 * @return (true:許可 false:拒否)
217 */
218 private boolean isValidAccess( final HttpServletRequest request ) {
219 if( ACCS_LVL == 0 ) { return true; } // レベル?:無条件アクセス
220
221 String httpReferer = request.getHeader( "Referer" );
222 String requestURI = request.getRequestURI();
223 String queryString = request.getQueryString();
224 String hashVal = request.getParameter( REQ_KEY );
225
226 if( isDebug ) {
227 System.out.println( "URLHashFilter#httpReferer = " + httpReferer );
228 System.out.println( "URLHashFilter#requestURI = " + requestURI );
229 }
230
231 // 基準となる許可?パラメータな?or ハッシュありの場?
232 boolean flag2 = ( queryString == null || hashVal != null ) ;
233
234 // レベル???:パラメータな?or ハッシュあり or Refererあり の場合?許可
235 if( ACCS_LVL == 1 || ACCS_LVL == 2 ) {
236 return ( flag2 || httpReferer != null );
237 }
238
239 // レベル?:パラメータな?or ハッシュありの場合?許可
240 if( ACCS_LVL == 3 ) {
241 String cntxPath = request.getContextPath(); // /gf など
242 // 特別処置
243 return flag2 ||
244 requestURI.equalsIgnoreCase( initPage ) ||
245 requestURI.startsWith( cntxPath + "/jsp/menu/" ) ||
246 requestURI.startsWith( cntxPath + "/jsp/custom/" ) ||
247 requestURI.startsWith( cntxPath + "/jsp/common/" ) ;
248 }
249
250 return false; // それ以外:無条件拒否
251 }
252
253 /**
254 * ?状態を??で返します?
255 *
256 * @return こ?クラスの??表示
257 */
258 @Override
259 public String toString() {
260 StringBuilder sb = new StringBuilder()
261 .append( this.getClass().getCanonicalName() ).append( " : ")
262 .append( "initPage = [" ).append( initPage ).append( "] , ")
263 // .append( "filename = [" ).append( filename ).append( "] , ")
264 .append( "isDebug = [" ).append( isDebug ).append( "]");
265 return (sb.toString());
266 }
267 }