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.lang.util.StringUtils; 022 023import javax.servlet.ServletRequest; 024import javax.servlet.ServletResponse; 025 026import java.util.ArrayList; 027import java.util.Collections; 028import java.util.List; 029import java.util.Collection; 030 031/** 032 * A Filter that requires the request to be from within a specific set of IP 033 * address ranges and / or not from with a specific (denied) set. 034 * <p/> 035 * Example config: 036 * <pre> 037 * [main] 038 * localLan = org.apache.shiro.web.filter.authz.IpFilter 039 * localLan.authorizedIps = 192.168.10.0/24 040 * localLan.deniedIps = 192.168.10.10/32 041 * <p/> 042 * [urls] 043 * /some/path/** = localLan 044 * # override for just this path: 045 * /another/path/** = localLan 046 * </pre> 047 * 048 * @since 2.0 049 */ 050public class IpFilter extends AuthorizationFilter { 051 052 private static final IpSource DEFAULT_IP_SOURCE = new IpSource() { 053 public Collection<String> getAuthorizedIps() { 054 return Collections.emptySet(); 055 } 056 057 public Collection<String> getDeniedIps() { 058 return Collections.emptySet(); 059 } 060 }; 061 062 private IpSource ipSource = DEFAULT_IP_SOURCE; 063 064 private List<IpAddressMatcher> authorizedIpMatchers = Collections.emptyList(); 065 private List<IpAddressMatcher> deniedIpMatchers = Collections.emptyList(); 066 067 /** 068 * Specifies a set of (comma, tab or space-separated) strings representing 069 * IP address representing IPv4 or IPv6 ranges / CIDRs from which access 070 * should be allowed (if the IP is not included in either the list of 071 * statically defined denied IPs or the dynamic list of IPs obtained from 072 * the IP source. 073 */ 074 public void setAuthorizedIps(String authorizedIps) { 075 String[] ips = StringUtils.tokenizeToStringArray(authorizedIps, ", \t"); 076 if (ips != null && ips.length > 0) { 077 authorizedIpMatchers = new ArrayList<IpAddressMatcher>(); 078 for (String ip : ips) { 079 authorizedIpMatchers.add(new IpAddressMatcher(ip)); 080 } 081 } 082 } 083 084 /** 085 * Specified a set of (comma, tab or space-separated) strings representing 086 * IP address representing IPv4 or IPv6 ranges / CIDRs from which access 087 * should be blocked. 088 */ 089 public void setDeniedIps(String deniedIps) { 090 String[] ips = StringUtils.tokenizeToStringArray(deniedIps, ", \t"); 091 if (ips != null && ips.length > 0) { 092 deniedIpMatchers = new ArrayList<IpAddressMatcher>(); 093 for (String ip : ips) { 094 deniedIpMatchers.add(new IpAddressMatcher(ip)); 095 } 096 } 097 } 098 099 public void setIpSource(IpSource source) { 100 this.ipSource = source; 101 } 102 103 /** 104 * Returns the remote host for a given HTTP request. By default uses the 105 * remote method ServletRequest.getRemoteAddr(). May be overridden by 106 * subclasses to obtain address information from specific headers (e.g. XFF 107 * or Forwarded) in situations with reverse proxies. 108 */ 109 public String getHostFromRequest(ServletRequest request) { 110 return request.getRemoteAddr(); 111 } 112 113 protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { 114 String remoteIp = getHostFromRequest(request); 115 for (IpAddressMatcher matcher : deniedIpMatchers) { 116 if (matcher.matches(remoteIp)) { 117 return false; 118 } 119 } 120 for (String ip : ipSource.getDeniedIps()) { 121 IpAddressMatcher matcher = new IpAddressMatcher(ip); 122 if (matcher.matches(remoteIp)) { 123 return false; 124 } 125 } 126 for (IpAddressMatcher matcher : authorizedIpMatchers) { 127 if (matcher.matches(remoteIp)) { 128 return true; 129 } 130 } 131 for (String ip : ipSource.getAuthorizedIps()) { 132 IpAddressMatcher matcher = new IpAddressMatcher(ip); 133 if (matcher.matches(remoteIp)) { 134 return true; 135 } 136 } 137 return false; 138 } 139}