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    }