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 org.opengion.hayabusa.common.HybsSystem;
019    
020    import java.io.File;                                                    // 5.7.3.2 (2014/02/28) Tomcat8 対�
021    import java.io.IOException;
022    import java.io.PrintWriter;
023    
024    import javax.servlet.Filter;
025    import javax.servlet.FilterChain;
026    import javax.servlet.FilterConfig;
027    import javax.servlet.ServletContext;
028    import javax.servlet.ServletException;
029    import javax.servlet.ServletRequest;
030    import javax.servlet.ServletResponse;
031    import javax.servlet.RequestDispatcher;
032    import javax.servlet.http.HttpServletResponse;
033    import javax.servlet.http.HttpServletRequest;
034    
035    import org.opengion.fukurou.security.URLHashMap;
036    import org.opengion.fukurou.util.StringUtil;
037    import org.opengion.fukurou.util.FileString;
038    
039    /**
040     * URLHashFilter ã¯ã€Filter インターフェースを継承ã—㟠URLãƒã‚§ãƒ?‚¯ã‚¯ãƒ©ã‚¹ã§ã™ã?
041     * web.xml ã§ filter 設定ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€å?ç?‚’é–‹å§‹ã—ã¾ã™ã?
042     * filter 処ç??ã€è¨­å®šãƒ¬ãƒ™ãƒ«ã¨URLã®é£›ã?å…ˆã«ã‚ˆã‚Šå‡¦ç?–¹æ³•ãŒç•°ãªã‚Šã¾ã™ã?
043     * ã“ã?フィルターã§ã¯ã€ãƒãƒ?‚·ãƒ¥åŒ?æš—å·åŒ–ã§ã¯ãªãã?ã‚¢ãƒ‰ãƒ¬ã‚¹ã«æˆ»ã™ä½œæ¥­ã«ãªã‚Šã¾ã™ã?
044     * å†?ƒ¨URLã®å ´åˆã?ãƒãƒƒã‚·ãƒ¥åŒ–ã?外部URLã®å ´åˆã?æš—å·åŒ–ã«é©ç”¨ã•れã¾ã™ã?
045     *
046     * 基本çš?«ã¯ã€å¤–部ã¸ã®URLã§ã‚¨ãƒ³ã‚¸ãƒ³ã‚·ã‚¹ãƒ?ƒ ã¸é£›ã?ã™å?åˆã?ã€æš—å·åŒ–ã«ãªã‚Šã¾ã™ã?
047     * å†?ƒ¨ã¸ã®URLã¯ã€åŸºæœ¬çš?«ã€ãƒ‘ラメータã®ã¿æš—å·åŒ–を行ã„ã¾ã™ã?ãªãŠã?直接画é¢IDã‚?
048     * æŒ?®šã—ã¦é£›ã?ã™å?åˆã‚’ã€æ­¢ã‚ã‚‹ã‹ã©ã?‹ã¯ã€è¨­å®šãƒ¬ãƒ™ãƒ«ã«ä¾å­˜ã—ã¾ã™ã?
049     *
050     * フィルターã®è¨­å®šãƒ¬ãƒ™ãƒ«ã¯ã€ã‚·ã‚¹ãƒ?ƒ ãƒªã‚½ãƒ¼ã‚¹ã® URL_ACCESS_SECURITY_LEVEL 変数ã§
051     * 設定ã—ã¾ã™ã?
052     * ãªãŠã?å?ƒ¬ãƒ™ãƒ«å…±é€šã§ã€æˆ»ã—å?ç??レベルã«é–¢ä¿‚ãªã実行ã•れã¾ã™ã?
053     *   レベル?:ãªã«ã‚‚制é™ã?ã‚りã¾ã›ã‚“ã€?
054     *   レベル?‘:Referer ãƒã‚§ãƒ?‚¯ã‚’行ã„ã¾ã™ã?ã¤ã¾ã‚Šã?URLを直接入力ã—ã¦ã‚‚動作ã—ã¾ã›ã‚“ã€?
055     *             ãŸã ã—ã?RefererãŒä»˜ã„ã¦ã•ãˆã?‚Œã°ã€ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’与ãˆã¾ã™ã?
056     *             Referer ç„¡ã—ã?å ´åˆã§ã‚‚ã?URLã«ãƒ‘ラメータãŒå­˜åœ¨ã—ãªã??ã¾ãŸã?ã€?
057     *             アドレスãŒãƒãƒ?‚·ãƒ¥åŒ?æš—å·åŒ–ã•れã¦ã?‚‹å ´åˆã?ã€ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã?
058     *             レベル?‘ã?å ´åˆã?ãƒãƒƒã‚·ãƒ¥æˆ»ã?è¤?ˆåŒ–å?ç??行ã„ã¾ã™ã?ã‚ãã¾ã§ã€ãƒãƒ?‚·ãƒ¥åŒ?
059     *             æš—å·åŒ–ã•れã¦ã?ªã??åˆã§ã‚‚ã?Refererã•ãˆã‚れã°ã€è¨±å¯ã™ã‚‹ã¨ã?†ã“ã¨ã§ã™ã?
060     *             (パラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚り or Refererã‚り ã®å ´åˆã?許å¯)
061     *   レベル?’:フィルター処ç?¨ã—ã¦ã¯ã€ãƒ¬ãƒ™ãƒ«?‘ã¨åŒã˜ã§ã™ã?
062     *             ç•°ãªã‚‹ã?ã¯ã€URLã®ãƒãƒƒã‚·ãƒ¥åŒ?æš—å·åŒ–å?ç?‚’ã€å¤–部URLã«å¯¾ã—ã¦ã®ã¿è¡Œã„ã¾ã™ã?
063     *             (パラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚り or Refererã‚り ã®å ´åˆã?許å¯)
064     *   レベル?“:URLã®ãƒ‘ラメータãŒãƒãƒ?‚·ãƒ¥åŒ?æš—å·åŒ–ã•れã¦ã?‚‹å¿?¦ãŒã‚りã¾ã™ã?
065     *             レベル?‘åŒæ§˜ã?URLã«ãƒ‘ラメータãŒå­˜åœ¨ã—ãªã??åˆã?ã€ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã?
066     *             レベル?‘ã¨ç•°ãªã‚‹ã?ã¯ã€ãƒ‘ラメータã¯å¿?šãƒãƒƒã‚·ãƒ¥åŒ–ã‹ã€æš—å·åŒ–ã•れã¦ã?‚‹
067     *             å¿?¦ãŒã‚ã‚‹ã¨ã?†ã“ã¨ã§ã™ã?(å†?ƒ¨/外部å•ã‚ã?
068     *             (パラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚り ã®å ´åˆã?許å¯)
069     *   ãã‚Œä»¥å¤–ï¼šã‚¢ã‚¯ã‚»ã‚¹ã‚’åœæ­¢ã—ã¾ã™ã?
070     *
071     * フィルターã«å¯¾ã—ã¦web.xml ã§ãƒ‘ラメータを設定ã—ã¾ã™ã?
072     *   ・filename   :åœæ­¢æ™‚メãƒ?‚»ãƒ¼ã‚¸è¡¨ç¤ºãƒ•ァイルå?ä¾?/jsp/custom/refuseAccess.html)
073     *   ・initPage   :æœ??ã«ã‚¢ã‚¯ã‚»ã‚¹ã•れるå?期画é¢ã‚¢ãƒ‰ãƒ¬ã‚¹(åˆæœŸå€¤:/jsp/index.jsp)
074     *   ・debug      :ãƒ?ƒãƒ?‚°ãƒ¡ãƒ?‚»ãƒ¼ã‚¸ã®è¡¨ç¤º(åˆæœŸå€¤:false)
075     *
076     * ã€WEB-INF/web.xmlã€?
077     *     <filter>
078     *         <filter-name>URLHashFilter</filter-name>
079     *         <filter-class>org.opengion.hayabusa.filter.URLHashFilter</filter-class>
080     *         <init-param>
081     *             <param-name>filename</param-name>
082     *             <param-value>/jsp/custom/refuseAccess.html</param-value>
083     *         </init-param>
084     *          <init-param>
085     *              <param-name>initPage</param-name>
086     *              <param-value>/jsp/index.jsp</param-value>
087     *          </init-param>
088     *          <init-param>
089     *              <param-name>debug</param-name>
090     *              <param-value>false</param-value>
091     *          </init-param>
092     *     </filter>
093     *
094     *     <filter-mapping>
095     *         <filter-name>URLHashFilter</filter-name>
096     *         <url-pattern>*.jsp</url-pattern>
097     *     </filter-mapping>
098     *
099     * @og.group フィルター処ç?
100     *
101     * @og.rev 5.2.2.0 (2010/11/01) æ–°è¦è¿½åŠ?
102     *
103     * @version  5.2.2.0 (2010/11/01)
104     * @author   Kazuhiko Hasegawa
105     * @since    JDK1.6,
106     */
107    public final class URLHashFilter implements Filter {
108            private static final String REQ_KEY = HybsSystem.URL_HASH_REQ_KEY ;
109    
110            private static final int ACCS_LVL = HybsSystem.sysInt( "URL_ACCESS_SECURITY_LEVEL" );
111    
112            private String          initPage        = "/jsp/index.jsp";
113    //      private String          filename        = null;                 // ã‚¢ã‚¯ã‚»ã‚¹æ‹’å¦æ™‚メãƒ?‚»ãƒ¼ã‚¸è¡¨ç¤ºãƒ•ァイルå?
114            private FileString      refuseMsg       = null;                 // ã‚¢ã‚¯ã‚»ã‚¹æ‹’å¦æ™‚メãƒ?‚»ãƒ¼ã‚¸ãƒ•ァイルã®å†?®¹(キャãƒ?‚·ãƒ¥)
115            private boolean         isDebug         = false;
116    
117            /**
118             * フィルター処ç?œ¬ä½“ã?メソãƒ?ƒ‰ã§ã™ã?
119             *
120             * @og.rev 5.3.0.0 (2010/12/01) æ–?­—化ã‘対策ã¨ã—ã¦ã€setCharacterEncoding を実行ã™ã‚‹ã?
121             *
122             * @param       request         ServletRequestオブジェク�
123             * @param       response        ServletResponseオブジェク�
124             * @param       chain           FilterChainオブジェク�
125             * @throws IOException 入出力エラーãŒç™ºç”Ÿã—ãŸã¨ã?
126             * @throws ServletException サーブレãƒ?ƒˆé–¢ä¿‚ã?エラーãŒç™ºç”Ÿã—ãŸå?åˆã?throw ã•れã¾ã™ã?
127             */
128            public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain ) throws IOException, ServletException {
129                    HttpServletRequest req = (HttpServletRequest)request ;
130                    req.setCharacterEncoding( "UTF-8" );    // 5.3.0.0 (2010/12/01)
131    
132                    if( isValidAccess( req ) ) {
133                            String h_r = req.getParameter( REQ_KEY );
134                            // ãƒãƒƒã‚·ãƒ¥åŒ–キーãŒå­˜åœ¨ã™ã‚‹ã€?
135                            if( h_r != null ) {
136                                    HttpServletResponse resp = ((HttpServletResponse)response);
137                                    String qu = URLHashMap.getValue( h_r );
138                                    // キーã«å¯¾ã™ã‚‹å®Ÿã‚¢ãƒ‰ãƒ¬ã‚¹ãŒå­˜åœ¨ã™ã‚‹ã€?
139                                    if( qu != null ) {
140                                            String requestURI = req.getRequestURI();                // /gf/jsp/index.jsp ãªã©
141                                            String cntxPath   = req.getContextPath();               // /gf ãªã©
142                                            // 自åˆ??身ã®ã‚³ãƒ³ãƒ?‚­ã‚¹ãƒˆã¨åŒã˜ãªã®ã§ã€forward ã§ãã‚‹ã€?
143                                            if( requestURI.startsWith( cntxPath ) ) {
144                                                    String url = requestURI.substring(cntxPath.length()) + "?" + qu ;
145                                                    RequestDispatcher rd = request.getRequestDispatcher( url );
146                                                    rd.forward( request,response );
147                                            }
148                                            // ãã†ã§ãªã??åˆã?リãƒ?‚¤ãƒ¬ã‚¯ãƒˆã™ã‚‹ã?
149                                            else {
150                                                    String url = resp.encodeRedirectURL( requestURI + "?" + qu );
151                                                    resp.sendRedirect( url );
152                                            }
153                                    }
154                                    // キーã«å¯¾ã™ã‚‹å®Ÿã‚¢ãƒ‰ãƒ¬ã‚¹ãŒå­˜åœ¨ã—ãªã??(行ã先無ã—ã?ケース)
155                                    else {
156                                            String url = resp.encodeRedirectURL( initPage );
157                                            resp.sendRedirect( url );
158                                    }
159                            }
160                            // ãƒãƒƒã‚·ãƒ¥åŒ–キーãŒå­˜åœ¨ã—ãªã??
161                            else {
162                                    chain.doFilter(request, response);
163                            }
164                    }
165                    else {
166                            // アクセス拒å¦ã‚’示ã™ãƒ¡ãƒ?‚»ãƒ¼ã‚¸ãƒ•ァイルã®å†?®¹ã‚’å?力ã™ã‚‹ã?
167                            response.setContentType( "text/html; charset=UTF-8" );
168                            PrintWriter out = response.getWriter();
169                            out.println( refuseMsg.getValue() );
170                            out.flush();
171                    }
172            }
173    
174            /**
175             * フィルターã®åˆæœŸå‡¦ç?ƒ¡ã‚½ãƒ?ƒ‰ã§ã™ã?
176             *
177             * フィルターã«å¯¾ã—ã¦web.xml ã§åˆæœŸãƒ‘ラメータを設定ã—ã¾ã™ã?
178             *   ・filename   :åœæ­¢æ™‚メãƒ?‚»ãƒ¼ã‚¸è¡¨ç¤ºãƒ•ァイルå?
179             *   ・initPage   :æœ??ã«ã‚¢ã‚¯ã‚»ã‚¹ã•れるå?期画é¢ã‚¢ãƒ‰ãƒ¬ã‚¹(åˆæœŸå€¤:/jsp/index.jsp)
180             *   ・debug      :ãƒ?ƒãƒ?‚°ãƒ¡ãƒ?‚»ãƒ¼ã‚¸ã®è¡¨ç¤º(åˆæœŸå€¤:false)
181             *
182             * @og.rev 5.7.3.2 (2014/02/28) Tomcat8 対応ã?getRealPath( "/" ) ã®äº’æ›æ€§ã®ãŸã‚ã®ä¿®æ­£ã€?
183             *
184             * @param config FilterConfigオブジェク�
185             */
186            public void init( final FilterConfig config ) {
187                    initPage = StringUtil.nval( config.getInitParameter("initPage"), initPage );
188                    isDebug  = StringUtil.nval( config.getInitParameter("debug")   , isDebug  );
189    
190                    ServletContext context = config.getServletContext();
191    //              String realPath = context.getRealPath( "/" );
192                    String realPath = context.getRealPath( "" ) + File.separator;           // 5.7.3.2 (2014/02/28) Tomcat8 対�
193    
194                    // アクセス拒å¦ã‚’示ã™ãƒ¡ãƒ?‚»ãƒ¼ã‚¸ãƒ•ァイルã®å†?®¹ã‚’管ç?™ã‚?FileString オブジェクトを構築ã™ã‚‹ã?
195                    String filename  = realPath + config.getInitParameter("filename");
196                    refuseMsg = new FileString();
197                    refuseMsg.setFilename( filename );
198                    refuseMsg.setEncode( "UTF-8" );
199            }
200    
201            /**
202             * フィルターã®çµ‚äº??ç?ƒ¡ã‚½ãƒ?ƒ‰ã§ã™ã?
203             *
204             */
205            public void destroy() {
206                    // ã“ã“ã§ã¯å‡¦ç?‚’行ã„ã¾ã›ã‚“ã€?
207            }
208    
209            /**
210             * フィルターã®å†?ƒ¨çŠ¶æ…‹ã‚’ãƒã‚§ãƒ?‚¯ã™ã‚‹ãƒ¡ã‚½ãƒ?ƒ‰ã§ã™ã?
211             *
212             * 判定æ¡ä»¶ã¯ã€URL_ACCESS_SECURITY_LEVEL 変数 ã«å¿œã˜ã¦ç•°ãªã‚Šã¾ã™ã?
213             *     レベル?:ãªã«ã‚‚制é™ã?ã‚りã¾ã›ã‚“ã€?
214             *     レベル?‘:Referer ãƒã‚§ãƒ?‚¯ã‚’行ã„ã¾ã™ã?ã¤ã¾ã‚Šã?URLを直接入力ã—ã¦ã‚‚動作ã—ã¾ã›ã‚“ã€?
215             *     レベル?’:URLã®ãƒãƒƒã‚·ãƒ¥åŒ?æš—å·åŒ–å?ç?‚’ã€å¤–部URLã«å¯¾ã—ã¦ã®ã¿è¡Œã„ã¾ã™ã?(ãƒã‚§ãƒ?‚¯ã¯ã€ãƒ¬ãƒ™ãƒ«?‘ã¨åŒç­?
216             *     レベル?“:URLã®ãƒ‘ラメータãŒãƒãƒ?‚·ãƒ¥åŒ?æš—å·åŒ–ã•れã¦ã?‚‹å¿?¦ãŒã‚りã¾ã™ã?
217             *     ãã‚Œä»¥å¤–ï¼šã‚¢ã‚¯ã‚»ã‚¹ã‚’åœæ­¢ã—ã¾ã™ã?
218             *
219             * @param request HttpServletRequestオブジェク�
220             *
221             * @return      (true:è¨±å¯  false:æ‹’å¦)
222             */
223            private boolean isValidAccess( final HttpServletRequest request ) {
224                    if( ACCS_LVL == 0 )      { return true;  }      // レベル?:無æ¡ä»¶ã‚¢ã‚¯ã‚»ã‚¹
225    
226                    String httpReferer = request.getHeader( "Referer" );
227                    String requestURI  = request.getRequestURI();
228                    String queryString = request.getQueryString();
229                    String hashVal     = request.getParameter( REQ_KEY );
230    
231                    if( isDebug ) {
232                            System.out.println( "URLHashFilter#httpReferer = " + httpReferer );
233                            System.out.println( "URLHashFilter#requestURI  = " + requestURI  );
234                    }
235    
236                    // 基準ã¨ãªã‚‹è¨±å¯?šãƒ‘ラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚りã®å ´å?
237                    boolean flag2 = ( queryString == null || hashVal != null ) ;
238    
239                    // レベル???’:パラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚り or Refererã‚り ã®å ´åˆã?許å¯
240                    if( ACCS_LVL == 1 || ACCS_LVL == 2 ) {
241                            return ( flag2 || httpReferer != null );
242                    }
243    
244                    // レベル?“:パラメータãªã?or ãƒãƒƒã‚·ãƒ¥ã‚りã®å ´åˆã?許å¯
245                    if( ACCS_LVL == 3 ) {
246                            String cntxPath = request.getContextPath();             // /gf ãªã©
247                            // 特別処置
248                            return flag2 ||
249                                              requestURI.equalsIgnoreCase( initPage )            ||
250                                              requestURI.startsWith( cntxPath + "/jsp/menu/"   ) ||
251                                              requestURI.startsWith( cntxPath + "/jsp/custom/" ) ||
252                                              requestURI.startsWith( cntxPath + "/jsp/common/" ) ;
253                    }
254    
255                    return false;   // ãれ以外:無æ¡ä»¶æ‹’å¦
256            }
257    
258            /**
259             * å†?ƒ¨çŠ¶æ…‹ã‚’æ–?­—å?ã§è¿”ã—ã¾ã™ã?
260             *
261             * @return      ã“ã?ã‚¯ãƒ©ã‚¹ã®æ–?­—å?表示
262             */
263            @Override
264            public String toString() {
265                    StringBuilder sb = new StringBuilder()
266                            .append( this.getClass().getCanonicalName() ).append( " : ")
267                            .append( "initPage = [" ).append( initPage ).append( "] , ")
268    //                      .append( "filename = [" ).append( filename ).append( "] , ")
269                            .append( "isDebug  = [" ).append( isDebug  ).append( "]");
270                    return (sb.toString());
271            }
272    }