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