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