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.filter;
017
018import org.opengion.fukurou.util.Closer;
019import org.opengion.fukurou.util.HybsDateUtil;
020import org.opengion.hayabusa.common.HybsSystem;
021
022import javax.servlet.ServletRequest;
023import javax.servlet.http.HttpServletRequest;
024import javax.servlet.ServletResponse;
025import javax.servlet.ServletException;
026import javax.servlet.ServletContext;
027import javax.servlet.Filter;
028import javax.servlet.FilterChain;
029import javax.servlet.FilterConfig;
030
031// import java.util.Date;
032// import java.util.Locale ;
033// import java.text.DateFormat;
034// import java.text.SimpleDateFormat;
035
036import java.io.File;                                                    // 5.7.3.2 (2014/02/28) Tomcat8 対応
037import java.io.PrintWriter;
038import java.io.BufferedReader;
039import java.io.IOException;
040import java.io.FileInputStream;
041import java.io.InputStreamReader;
042import java.io.UnsupportedEncodingException;
043
044/**
045 * AccessStopFilter は、Filter インターフェースを継承した アクセス制御クラスです。
046 * web.xml で filter 設定することにより、Webアプリケーションへのアクセスを制御できます。
047 * また、SYSTEM ユーザーは、このフィルターを常に通過します。
048 *
049 * フィルターに対してweb.xml でパラメータを設定します。
050 *   ・startTime:停止開始時刻
051 *   ・stopTime :停止終了時刻
052 *   ・filename :停止時メッセージ表示ファイル名
053 *
054 * 【WEB-INF/web.xml】
055 *     <filter>
056 *         <filter-name>AccessStopFilter</filter-name>
057 *         <filter-class>org.opengion.hayabusa.filter.AccessStopFilter</filter-class>
058 *         <init-param>
059 *             <param-name>startTime</param-name>
060 *             <param-value>070000</param-value>
061 *         </init-param>
062 *         <init-param>
063 *             <param-name>stopTime</param-name>
064 *             <param-value>070000</param-value>
065 *         </init-param>
066 *         <init-param>
067 *             <param-name>filename</param-name>
068 *             <param-value>jsp/custom/stopFile.html</param-value>
069 *         </init-param>
070 *     </filter>
071 *
072 *     <filter-mapping>
073 *         <filter-name>AccessStopFilter</filter-name>
074 *         <url-pattern>/jsp/*</url-pattern>
075 *     </filter-mapping>
076 *
077 * @og.group フィルター処理
078 *
079 * @version  4.0
080 * @author   Kazuhiko Hasegawa
081 * @since    JDK5.0,
082 */
083public final class AccessStopFilter implements Filter {
084
085        private static boolean stopFilter = false;
086        private String startTime = "230000";            // 停止開始時刻
087        private String stopTime  = "070000";            // 停止終了時刻
088        private String filename  = null;                        // 停止時メッセージ表示ファイル名
089        private int    startStop = 0;
090        
091        private static final String  USERID_HEADER = HybsSystem.sys( "USERID_HEADER_NAME" ); // 5.10.18.0 (2019/11/29)
092
093        /**
094         * フィルター処理本体のメソッドです。
095         *
096         * @og.rev 3.1.3.0 (2003/04/10) UTF-8 決め打ちで、stopFile.html を返送する。
097         * @og.rev 3.1.8.0 (2003/05/16) 文字エンコードが、UTF-8 になっていないのを修正。
098         *
099         * @param       request         ServletRequestオブジェクト
100         * @param       response        ServletResponseオブジェクト
101         * @param       chain           FilterChainオブジェクト
102         * @throws IOException 入出力エラーが発生した場合、throw されます。
103         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
104         */
105        public void doFilter( final ServletRequest request,
106                                                        final ServletResponse response,
107                                                        final FilterChain chain)
108                                                                throws IOException, ServletException {
109
110                if( isStop( request ) ) {
111                        BufferedReader in = null ;
112                        try {
113                                response.setContentType( "text/html; charset=UTF-8" );
114                                PrintWriter out = response.getWriter();
115                                in = new BufferedReader( new InputStreamReader(
116                                                                new FileInputStream( filename ) ,"UTF-8" ) );
117                                String str ;
118                                while( (str = in.readLine()) != null ) {
119                                        out.println( str );
120                                }
121                                out.flush();
122                        }
123                        catch( UnsupportedEncodingException ex ) {
124                                String errMsg = "指定されたエンコーディングがサポートされていません。[UTF-8]" ;
125                                throw new RuntimeException( errMsg,ex );
126                        }
127                        catch( IOException ex ) {
128                                String errMsg = "ストリームがオープン出来ませんでした。[" + filename + "]" ;
129                                throw new RuntimeException( errMsg,ex );
130                        }
131                        finally {
132                                Closer.ioClose( in );
133                        }
134                        return;
135                }
136
137                chain.doFilter(request, response);
138        }
139
140        /**
141         * フィルターの初期処理メソッドです。
142         *
143         * フィルターに対してweb.xml で初期パラメータを設定します。
144         *   ・startTime:停止開始時刻
145         *   ・stopTime :停止終了時刻
146         *   ・filename :停止時メッセージ表示ファイル名
147         *
148         * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応。getRealPath( "/" ) の互換性のための修正。
149         *
150         * @param       filterConfig    FilterConfigオブジェクト
151         */
152        public void init(final FilterConfig filterConfig) {
153
154                ServletContext context = filterConfig.getServletContext();
155//              String realPath = context.getRealPath( "/" );
156                String realPath = context.getRealPath( "" ) + File.separator;   // 5.7.3.2 (2014/02/28) Tomcat8 対応
157
158                startTime = filterConfig.getInitParameter("startTime");
159                stopTime  = filterConfig.getInitParameter("stopTime");
160                filename  = realPath + filterConfig.getInitParameter("filename");
161
162                if( startTime == null || stopTime == null ) {
163                        startStop = 0;
164                }
165                else {
166                        startStop = startTime.compareTo( stopTime );
167                }
168        }
169
170        /**
171         * フィルターの終了処理メソッドです。
172         *
173         */
174        public void destroy() {
175                // ここでは処理を行いません。
176        }
177
178        /**
179         * フィルターの内部状態をチェックするメソッドです。
180         * 内部のフラグをもとに、停止/許可を求めます。
181         *
182         * @og.rev 3.1.8.0 (2003/05/16) 開始時刻と終了時刻を同一にしていると、画面からの制御が効かないバグを修正。
183         * @og.rev 5.5.3.2 (2012/06/08) 通過させるユーザーに、admin を追加します。
184         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
185         * @og.rev 5.10.18.0 (2019/11/29) ヘッダ認証
186         *
187         * @param request ServletRequestオブジェクト
188         *
189         * @return      (true:停止  false:実行許可)
190         */
191        private boolean isStop( final ServletRequest request ) {
192                String userID = ((HttpServletRequest)request).getRemoteUser() ;
193                if( USERID_HEADER != null && USERID_HEADER.length() > 0 && ( userID == null || userID.length() == 0) ) {
194                        userID = ((HttpServletRequest)request).getHeader( USERID_HEADER );
195                }
196                
197                
198                // 5.5.3.2 (2012/06/08) 通過させるユーザーに、admin を追加
199//              if( "SYSTEM".equalsIgnoreCase( userID ) ) {
200                if( "SYSTEM".equalsIgnoreCase( userID ) || "admin".equalsIgnoreCase( userID ) ) {
201                        return false;
202                }
203
204                // 4.0.0 (2005/01/31)
205//              DateFormat formatter = new SimpleDateFormat( "HHmmss",Locale.JAPAN );
206//              String time = formatter.format( new Date() );
207                String time = HybsDateUtil.getDate( "HHmmss" );         // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
208
209                boolean rtnFlag = stopFilter;
210                if( startStop < 0 ) {
211                        if( startTime.compareTo( time ) < 0 &&
212                                time.compareTo( stopTime )  < 0 ) {
213                                        rtnFlag = true;
214                        }
215                }
216                else if( startStop > 0 ) {
217                        if( startTime.compareTo( time ) < 0 ||
218                                time.compareTo( stopTime )  < 0 ) {
219                                        rtnFlag = true;
220                                }
221                }
222                return rtnFlag;
223        }
224
225        /**
226         * フィルターの強制停止/解除を設定するメソッドです。
227         *
228         * @og.rev 4.0.0.0 (2005/01/31) synchronized の廃止
229         *
230         * @param flag (true:停止  false:実行許可)
231         */
232        public static void setStopFilter( final boolean flag ) {
233                stopFilter = flag;
234        }
235
236        /**
237         * フィルターの内部状態(強制停止/解除)を取得するメソッドです。
238         * これは、現在、アクセス制限がどうなっているかという状態ではなく、
239         * 強制停止されているかどうかの確認メソッドです。
240         *
241         * @og.rev 4.0.0.0 (2007/11/29) getStopFilter() ⇒ isStopFilter() に変更
242         *
243         * @return      (true:停止  false:実行許可)
244         */
245//      public static boolean getStopFilter() {
246        public static boolean isStopFilter() {
247                return stopFilter;
248        }
249
250        /**
251         * 内部状態を文字列で返します。
252         *
253         * @return      このクラスの文字列表示
254         */
255        @Override
256        public String toString() {
257                StringBuilder sb = new StringBuilder();
258                sb.append( "AccessStopFilter" );
259                sb.append( "[" ).append( startTime ).append( "],");
260                sb.append( "[" ).append( stopTime  ).append( "],");
261                sb.append( "[" ).append( filename  ).append( "],");
262                return (sb.toString());
263        }
264}