001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.shiro.web.filter.authz; 020 021import org.apache.shiro.config.ConfigurationException; 022import org.apache.shiro.lang.util.StringUtils; 023import org.apache.shiro.web.util.WebUtils; 024 025import javax.servlet.ServletRequest; 026import javax.servlet.ServletResponse; 027import javax.servlet.http.HttpServletRequest; 028import java.io.IOException; 029 030/** 031 * A Filter that requires the request to be on a specific port, and if not, redirects to the same URL on that port. 032 * <p/> 033 * Example config: 034 * <pre> 035 * [filters] 036 * port.port = 80 037 * <p/> 038 * [urls] 039 * /some/path/** = port 040 * # override for just this path: 041 * /another/path/** = port[8080] 042 * </pre> 043 * 044 * @since 1.0 045 */ 046@SuppressWarnings("checkstyle:JavadocVariable") 047public class PortFilter extends AuthorizationFilter { 048 049 public static final int DEFAULT_HTTP_PORT = 80; 050 public static final String HTTP_SCHEME = "http"; 051 052 private int port = DEFAULT_HTTP_PORT; 053 054 public int getPort() { 055 return port; 056 } 057 058 public void setPort(int port) { 059 this.port = port; 060 } 061 062 protected int toPort(Object mappedValue) { 063 String[] ports = (String[]) mappedValue; 064 if (ports == null || ports.length == 0) { 065 return getPort(); 066 } 067 if (ports.length > 1) { 068 throw new ConfigurationException("PortFilter can only be configured with a single port. You have " 069 + "configured " + ports.length + ": " + StringUtils.toString(ports)); 070 } 071 return Integer.parseInt(ports[0]); 072 } 073 074 protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { 075 int requiredPort = toPort(mappedValue); 076 int requestPort = request.getServerPort(); 077 return requiredPort == requestPort; 078 } 079 080 protected String getScheme(String requestScheme, int port) { 081 if (port == DEFAULT_HTTP_PORT) { 082 return HTTP_SCHEME; 083 } else if (port == SslFilter.DEFAULT_HTTPS_PORT) { 084 return SslFilter.HTTPS_SCHEME; 085 } else { 086 return requestScheme; 087 } 088 } 089 090 /** 091 * Redirects the request to the same exact incoming URL, but with the port listed in the filter's configuration. 092 * 093 * @param request the incoming <code>ServletRequest</code> 094 * @param response the outgoing <code>ServletResponse</code> 095 * @param mappedValue the config specified for the filter in the matching request's filter chain. 096 * @return {@code false} always to force a redirect. 097 */ 098 @Override 099 protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { 100 101 //just redirect to the specified port: 102 int port = toPort(mappedValue); 103 104 String scheme = getScheme(request.getScheme(), port); 105 106 StringBuilder sb = new StringBuilder(); 107 sb.append(scheme).append("://"); 108 sb.append(request.getServerName()); 109 if (port != DEFAULT_HTTP_PORT && port != SslFilter.DEFAULT_HTTPS_PORT) { 110 sb.append(":"); 111 sb.append(port); 112 } 113 if (request instanceof HttpServletRequest) { 114 sb.append(WebUtils.toHttp(request).getRequestURI()); 115 String query = WebUtils.toHttp(request).getQueryString(); 116 if (query != null) { 117 sb.append("?").append(query); 118 } 119 } 120 121 WebUtils.issueRedirect(request, response, sb.toString()); 122 123 return false; 124 } 125}