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.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 */ 046public class PortFilter extends AuthorizationFilter { 047 048 public static final int DEFAULT_HTTP_PORT = 80; 049 public static final String HTTP_SCHEME = "http"; 050 051 private int port = DEFAULT_HTTP_PORT; 052 053 public int getPort() { 054 return port; 055 } 056 057 public void setPort(int port) { 058 this.port = port; 059 } 060 061 protected int toPort(Object mappedValue) { 062 String[] ports = (String[]) mappedValue; 063 if (ports == null || ports.length == 0) { 064 return getPort(); 065 } 066 if (ports.length > 1) { 067 throw new ConfigurationException("PortFilter can only be configured with a single port. You have " + 068 "configured " + ports.length + ": " + StringUtils.toString(ports)); 069 } 070 return Integer.parseInt(ports[0]); 071 } 072 073 protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { 074 int requiredPort = toPort(mappedValue); 075 int requestPort = request.getServerPort(); 076 return requiredPort == requestPort; 077 } 078 079 protected String getScheme(String requestScheme, int port) { 080 if (port == DEFAULT_HTTP_PORT) { 081 return HTTP_SCHEME; 082 } else if (port == SslFilter.DEFAULT_HTTPS_PORT) { 083 return SslFilter.HTTPS_SCHEME; 084 } else { 085 return requestScheme; 086 } 087 } 088 089 /** 090 * Redirects the request to the same exact incoming URL, but with the port listed in the filter's configuration. 091 * 092 * @param request the incoming <code>ServletRequest</code> 093 * @param response the outgoing <code>ServletResponse</code> 094 * @param mappedValue the config specified for the filter in the matching request's filter chain. 095 * @return {@code false} always to force a redirect. 096 */ 097 @Override 098 protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { 099 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}