View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.web.filter.authz;
20  
21  import org.apache.shiro.config.ConfigurationException;
22  import org.apache.shiro.util.StringUtils;
23  import org.apache.shiro.web.util.WebUtils;
24  
25  import javax.servlet.ServletRequest;
26  import javax.servlet.ServletResponse;
27  import javax.servlet.http.HttpServletRequest;
28  import java.io.IOException;
29  
30  /**
31   * A Filter that requires the request to be on a specific port, and if not, redirects to the same URL on that port.
32   * <p/>
33   * Example config:
34   * <pre>
35   * [filters]
36   * port.port = 80
37   * <p/>
38   * [urls]
39   * /some/path/** = port
40   * # override for just this path:
41   * /another/path/** = port[8080]
42   * </pre>
43   *
44   * @since 1.0
45   */
46  public class PortFilter extends AuthorizationFilter {
47  
48      public static final int DEFAULT_HTTP_PORT = 80;
49      public static final String HTTP_SCHEME = "http";
50  
51      private int port = DEFAULT_HTTP_PORT;
52  
53      public int getPort() {
54          return port;
55      }
56  
57      public void setPort(int port) {
58          this.port = port;
59      }
60  
61      protected int toPort(Object mappedValue) {
62          String[] ports = (String[]) mappedValue;
63          if (ports == null || ports.length == 0) {
64              return getPort();
65          }
66          if (ports.length > 1) {
67              throw new ConfigurationException("PortFilter can only be configured with a single port.  You have " +
68                      "configured " + ports.length + ": " + StringUtils.toString(ports));
69          }
70          return Integer.parseInt(ports[0]);
71      }
72  
73      protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
74          int requiredPort = toPort(mappedValue);
75          int requestPort = request.getServerPort();
76          return requiredPort == requestPort;
77      }
78  
79      protected String getScheme(String requestScheme, int port) {
80          if (port == DEFAULT_HTTP_PORT) {
81              return HTTP_SCHEME;
82          } else if (port == SslFilter.DEFAULT_HTTPS_PORT) {
83              return SslFilter.HTTPS_SCHEME;
84          } else {
85              return requestScheme;
86          }
87      }
88  
89      /**
90       * Redirects the request to the same exact incoming URL, but with the port listed in the filter's configuration.
91       *
92       * @param request     the incoming <code>ServletRequest</code>
93       * @param response    the outgoing <code>ServletResponse</code>
94       * @param mappedValue the config specified for the filter in the matching request's filter chain.
95       * @return {@code false} always to force a redirect.
96       */
97      @Override
98      protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
99  
100         //just redirect to the specified port:
101         int port = toPort(mappedValue);
102 
103         String scheme = getScheme(request.getScheme(), port);
104 
105         StringBuilder sb = new StringBuilder();
106         sb.append(scheme).append("://");
107         sb.append(request.getServerName());
108         if (port != DEFAULT_HTTP_PORT && port != SslFilter.DEFAULT_HTTPS_PORT) {
109             sb.append(":");
110             sb.append(port);
111         }
112         if (request instanceof HttpServletRequest) {
113             sb.append(WebUtils.toHttp(request).getRequestURI());
114             String query = WebUtils.toHttp(request).getQueryString();
115             if (query != null) {
116                 sb.append("?").append(query);
117             }
118         }
119 
120         WebUtils.issueRedirect(request, response, sb.toString());
121 
122         return false;
123     }
124 }