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 java.io.File; // 5.7.3.2 (2014/02/28) Tomcat8 対?
019 import java.io.BufferedReader;
020 import java.io.FileInputStream;
021 import java.io.IOException;
022 import java.io.InputStreamReader;
023 import java.io.PrintWriter;
024 import java.io.UnsupportedEncodingException;
025
026 import javax.servlet.Filter;
027 import javax.servlet.FilterChain;
028 import javax.servlet.FilterConfig;
029 import javax.servlet.ServletContext;
030 import javax.servlet.ServletException;
031 import javax.servlet.ServletRequest;
032 import javax.servlet.ServletResponse;
033 import javax.servlet.http.HttpServletRequest;
034
035 import org.opengion.fukurou.security.HybsCryptography;
036 import org.opengion.fukurou.util.Closer;
037 import org.opengion.fukurou.util.StringUtil;
038 import org.opengion.hayabusa.common.HybsSystem;
039
040 /**
041 * URLCheckFilter は、Filter インターフェースを継承した URLチェ?クラスです?
042 * web.xml で filter 設定することにより、該当?リソースに対して、og:linkタグで?
043 * useURLCheck="true"が指定されたリンクURL以外を拒否することができます?
044 * また?og:linkタグを経由した場合でも?リンクの有効期限を設定することで?
045 * リンクURLの漏洩に対しても??時間?経過を持って、アクセスを拒否することができます?
046 * また?リンク時にユーザー??も埋め込んで?す?で(初期値は、ログインユーザー)?
047 * リンクアドレスが他?ユーザーに知られた?合でも?アクセスを拒否することができます?
048 *
049 * フィルターに対してweb.xml でパラメータを設定します?
050 * ・filename :停止時メ?ージ表示ファイル?
051 * ・ignoreURL:暗号化されたURLの?空白に置き換える接頭??を指定します?
052 * 外部からアクセスしたURLがロードバランサで?向けURLに変換されてチェ?が動作しな??場合に
053 * 利用します?https://wwwX.のように?します?通常は設定しません?
054 *
055 * 【WEB-INF/web.xml?
056 * <filter>
057 * <filter-name>URLCheckFilter</filter-name>
058 * <filter-class>org.opengion.hayabusa.filter.URLCheckFilter</filter-class>
059 * <init-param>
060 * <param-name>filename</param-name>
061 * <param-value>jsp/custom/refuseAccess.html</param-value>
062 * </init-param>
063 * </filter>
064 *
065 * <filter-mapping>
066 * <filter-name>URLCheckFilter</filter-name>
067 * <url-pattern>/jsp/*</url-pattern>
068 * </filter-mapping>
069 *
070 * @og.group フィルター処?
071 *
072 * @version 4.0
073 * @author Hiroki Nakamura
074 * @since JDK5.0,
075 */
076 public final class URLCheckFilter implements Filter {
077
078 private static final HybsCryptography HYBS_CRYPTOGRAPHY = new HybsCryptography(); // 4.3.7.0 (2009/06/01)
079
080 private String filename = null; // アクセス拒否時メ?ージ表示ファイル?
081 // private int maxInterval = 3600; // リンクの有効期限
082 private boolean isDebug = false;
083 private boolean isDecode = true; // 5.4.5.0(2012/02/28) URIDecodeするかど?
084
085 private String ignoreURL = null; //5.8.6.1 (2015/04/17) 飛んできたcheckURLから取り除くURL??
086
087 /**
088 * フィルター処?体?メソ?です?
089 *
090 * @param request ServletRequestオブジェク?
091 * @param response ServletResponseオブジェク?
092 * @param chain FilterChainオブジェク?
093 * @throws ServletException サーブレ?関係?エラーが発生した?合?throw されます?
094 */
095 public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain ) throws IOException, ServletException {
096
097 if( !isValidAccess( request ) ) {
098 BufferedReader in = null ;
099 try {
100 response.setContentType( "text/html; charset=UTF-8" );
101 PrintWriter out = response.getWriter();
102 in = new BufferedReader( new InputStreamReader(
103 new FileInputStream( filename ) ,"UTF-8" ) );
104 String str ;
105 while( (str = in.readLine()) != null ) {
106 out.println( str );
107 }
108 out.flush();
109 }
110 catch( UnsupportedEncodingException ex ) {
111 String errMsg = "?されたエンコー?ングがサポ?トされて?せん?UTF-8]" ;
112 throw new RuntimeException( errMsg,ex );
113 }
114 catch( IOException ex ) {
115 String errMsg = "ストリー?オープン出来ませんでした?" + filename + "]" ;
116 throw new RuntimeException( errMsg,ex );
117 }
118 finally {
119 Closer.ioClose( in );
120 }
121 return;
122 }
123
124 chain.doFilter(request, response);
125 }
126
127 /**
128 * フィルターの初期処?ソ?です?
129 *
130 * フィルターに対してweb.xml で初期パラメータを設定します?
131 * ・maxInterval:リンクの有効期限
132 * ・filename :停止時メ?ージ表示ファイル?
133 * ・decode :URL?ードを行ってチェ?する?初期true)
134 *
135 * @og.rev 5.4.5.0 (2102/02/28)
136 * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応?getRealPath( "/" ) の互換性のための修正?
137 * @og.rev 5.8.6.1 (2015/04/17) DMZのURL変換対?
138 *
139 * @param filterConfig FilterConfigオブジェク?
140 */
141 public void init(final FilterConfig filterConfig) {
142 ServletContext context = filterConfig.getServletContext();
143 // String realPath = context.getRealPath( "/" );
144 String realPath = context.getRealPath( "" ) + File.separator; // 5.7.3.2 (2014/02/28) Tomcat8 対?
145
146 // maxInterval = StringUtil.nval( filterConfig.getInitParameter("maxInterval"), maxInterval );
147 filename = realPath + filterConfig.getInitParameter("filename");
148 isDebug = StringUtil.nval( filterConfig.getInitParameter("debug"), false );
149 isDecode = StringUtil.nval( filterConfig.getInitParameter("decode"), true ); // 5.4.5.0(2012/02/28)
150 ignoreURL = filterConfig.getInitParameter("ignoreURL"); // 5.8.6.1 (2015/04/17)
151 }
152
153 /**
154 * フィルターの終???ソ?です?
155 *
156 */
157 public void destroy() {
158 // ここでは処?行いません?
159 }
160
161 /**
162 * フィルターの?状態をチェ?するメソ?です?
163 *
164 * @og.rev 5.4.5.0 (2012/02/28) Decode
165 *
166 * @param request ServletRequestオブジェク?
167 *
168 * @return (true:許可 false:拒否)
169 */
170 private boolean isValidAccess( final ServletRequest request ) {
171 String checkKey = request.getParameter( HybsSystem.URL_CHECK_KEY );
172 if( checkKey == null || checkKey.length() == 0 ) {
173 if( isDebug ) {
174 System.out.println( " check NG [ No Check Key ]" );
175 }
176 return false;
177 }
178
179 boolean rtn = false;
180 try {
181 checkKey = HYBS_CRYPTOGRAPHY.decrypt( checkKey ).replace( "&", "&" );
182
183 if( isDebug ) {
184 System.out.println( "checkKey=" + checkKey );
185 }
186
187 String url = checkKey.substring( 0 , checkKey.lastIndexOf( ",time=") );
188 long time = Long.parseLong( checkKey.substring( checkKey.lastIndexOf( ",time=") + 6, checkKey.lastIndexOf( ",userid=" ) ) );
189 String userid = checkKey.substring( checkKey.lastIndexOf( ",userid=") + 8 );
190 // 4.3.8.0 (2009/08/01)
191 String[] userArr = StringUtil.csv2Array( userid );
192
193 // 5.8.6.1 (2015/04/17)ignoreURL対?
194 if( ignoreURL!=null && ignoreURL.length()>0 && url.indexOf( ignoreURL ) == 0 ){
195 url = url.substring( ignoreURL.length() );
196 }
197
198 if( isDebug ) {
199 System.out.println( " [ignoreURL]=" + ignoreURL ); // 2015/04/17 (2015/04/17)
200 System.out.println( " [url] =" + url );
201 System.out.println( " [vtime] =" + time );
202 System.out.println( " [userid] =" + userid );
203 }
204
205 String reqStr = ((HttpServletRequest)request).getRequestURL().toString() + "?" + ((HttpServletRequest)request).getQueryString();
206 // 5.4.5.0 (2012/02/28) URLDecodeを行う
207 if(isDecode){
208 if( isDebug ) {
209 System.out.println( "[BeforeURIDecode]="+reqStr );
210 }
211 reqStr = StringUtil.urlDecode( reqStr );
212 }
213 reqStr = reqStr.substring( 0, reqStr.lastIndexOf( HybsSystem.URL_CHECK_KEY ) -1 );
214 // String reqStr = ((HttpServletRequest)request).getRequestURL().toString();
215 String reqUser = ((HttpServletRequest)request).getRemoteUser();
216
217 if( isDebug ) {
218 System.out.println( " [reqURL] =" + reqStr );
219 System.out.println( " [ctime] =" + System.currentTimeMillis() );
220 System.out.println( " [reqUser]=" + reqUser );
221 }
222
223 if( reqStr.endsWith( url )
224 // && System.currentTimeMillis() - time < maxInterval * 1000
225 && System.currentTimeMillis() - time < 0
226 // && userid.equals( reqUser ) ) {
227 && userArr != null && userArr.length > 0 ) {
228 // 4.3.8.0 (2009/08/01)
229 for( int i=0; i<userArr.length; i++ ) {
230 if( "*".equals( userArr[i] ) || reqUser.equals( userArr[i] ) ) {
231 rtn = true;
232 if( isDebug ) {
233 System.out.println( " check OK" );
234 }
235 break;
236 }
237 }
238 }
239 }
240 catch( RuntimeException ex ) {
241 if( isDebug ) {
242 String errMsg = "チェ?エラー?"
243 + " checkKey=" + checkKey
244 + " " + ex.getMessage(); // 5.1.8.0 (2010/07/01) errMsg 修正
245 System.out.println( errMsg );
246 ex.printStackTrace();
247 }
248 rtn = false;
249 }
250 return rtn;
251 }
252
253 /**
254 * ?状態を??で返します?
255 *
256 * @return こ?クラスの??表示
257 */
258 @Override
259 public String toString() {
260 StringBuilder sb = new StringBuilder();
261 sb.append( "UrlCheckFilter" );
262 // sb.append( "[" ).append( maxInterval ).append( "],");
263 sb.append( "[" ).append( filename ).append( "],");
264 return (sb.toString());
265 }
266 }