mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 00:32:14 +00:00
SEC-2357: Fix package cycles
This commit is contained in:
parent
14b9050616
commit
45ad74a0bd
@ -14,7 +14,12 @@ package org.springframework.security.web.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Matcher which compares a pre-defined ant-style pattern against the URL
|
||||
@ -39,7 +44,13 @@ import org.springframework.util.AntPathMatcher;
|
||||
* @see org.springframework.util.AntPathMatcher
|
||||
*/
|
||||
public final class AntPathRequestMatcher implements RequestMatcher {
|
||||
private final org.springframework.security.web.util.matchers.AntPathRequestMatcher delegate;
|
||||
private static final Log logger = LogFactory.getLog(AntPathRequestMatcher.class);
|
||||
private static final String MATCH_ALL = "/**";
|
||||
|
||||
private final Matcher matcher;
|
||||
private final String pattern;
|
||||
private final HttpMethod httpMethod;
|
||||
private final boolean caseSensitive;
|
||||
|
||||
/**
|
||||
* Creates a matcher with the specific pattern which will match all HTTP
|
||||
@ -79,7 +90,28 @@ public final class AntPathRequestMatcher implements RequestMatcher {
|
||||
* true if the matcher should consider case, else false
|
||||
*/
|
||||
public AntPathRequestMatcher(String pattern, String httpMethod, boolean caseSensitive) {
|
||||
this.delegate = new org.springframework.security.web.util.matchers.AntPathRequestMatcher(pattern, httpMethod, caseSensitive);
|
||||
Assert.hasText(pattern, "Pattern cannot be null or empty");
|
||||
this.caseSensitive = caseSensitive;
|
||||
|
||||
if (pattern.equals(MATCH_ALL) || pattern.equals("**")) {
|
||||
pattern = MATCH_ALL;
|
||||
matcher = null;
|
||||
} else {
|
||||
if(!caseSensitive) {
|
||||
pattern = pattern.toLowerCase();
|
||||
}
|
||||
|
||||
// If the pattern ends with {@code /**} and has no other wildcards, then optimize to a sub-path match
|
||||
if (pattern.endsWith(MATCH_ALL) && pattern.indexOf('?') == -1 &&
|
||||
pattern.indexOf("*") == pattern.length() - 2) {
|
||||
matcher = new SubpathMatcher(pattern.substring(0, pattern.length() - 3));
|
||||
} else {
|
||||
matcher = new SpringAntMatcher(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
this.pattern = pattern;
|
||||
this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,29 +121,125 @@ public final class AntPathRequestMatcher implements RequestMatcher {
|
||||
* {@code servletPath} + {@code pathInfo} of the request.
|
||||
*/
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return this.delegate.matches(request);
|
||||
if (httpMethod != null && request.getMethod() != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Request '" + request.getMethod() + " " + getRequestPath(request) + "'"
|
||||
+ " doesn't match '" + httpMethod + " " + pattern);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pattern.equals(MATCH_ALL)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Request '" + getRequestPath(request) + "' matched by universal pattern '/**'");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String url = getRequestPath(request);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Checking match of request : '" + url + "'; against '" + pattern + "'");
|
||||
}
|
||||
|
||||
return matcher.matches(url);
|
||||
}
|
||||
|
||||
public org.springframework.security.web.util.matchers.AntPathRequestMatcher getDelegate() {
|
||||
return delegate;
|
||||
private String getRequestPath(HttpServletRequest request) {
|
||||
String url = request.getServletPath();
|
||||
|
||||
if (request.getPathInfo() != null) {
|
||||
url += request.getPathInfo();
|
||||
}
|
||||
|
||||
if(!caseSensitive) {
|
||||
url = url.toLowerCase();
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return delegate.getPattern();
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public HttpMethod getHttpMethod() {
|
||||
return httpMethod;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return caseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return delegate.equals(obj);
|
||||
if (!(obj instanceof AntPathRequestMatcher)) {
|
||||
return false;
|
||||
}
|
||||
AntPathRequestMatcher other = (AntPathRequestMatcher)obj;
|
||||
return this.pattern.equals(other.pattern) &&
|
||||
this.httpMethod == other.httpMethod &&
|
||||
this.caseSensitive == other.caseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
int code = 31 ^ pattern.hashCode();
|
||||
if (httpMethod != null) {
|
||||
code ^= httpMethod.hashCode();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Ant [pattern='").append(pattern).append("'");
|
||||
|
||||
if (httpMethod != null) {
|
||||
sb.append(", ").append(httpMethod);
|
||||
}
|
||||
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static interface Matcher {
|
||||
boolean matches(String path);
|
||||
}
|
||||
|
||||
private static class SpringAntMatcher implements Matcher {
|
||||
private static final AntPathMatcher antMatcher = new AntPathMatcher();
|
||||
|
||||
private final String pattern;
|
||||
|
||||
private SpringAntMatcher(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public boolean matches(String path) {
|
||||
return antMatcher.match(pattern, path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized matcher for trailing wildcards
|
||||
*/
|
||||
private static class SubpathMatcher implements Matcher {
|
||||
private final String subpath;
|
||||
private final int length;
|
||||
|
||||
private SubpathMatcher(String subpath) {
|
||||
assert !subpath.contains("*");
|
||||
this.subpath = subpath;
|
||||
this.length = subpath.length();
|
||||
}
|
||||
|
||||
public boolean matches(String path) {
|
||||
return path.startsWith(subpath) && (path.length() == length || path.charAt(length) == '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,19 +10,18 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* @deprecated use org.springframework.security.web.util.matchers.AnyRequestMatcher.INSTANCE instead
|
||||
*/
|
||||
public final class AnyRequestMatcher implements RequestMatcher {
|
||||
private final RequestMatcher delegate = org.springframework.security.web.util.matchers.AnyRequestMatcher.INSTANCE;
|
||||
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return delegate.matches(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return delegate.equals(obj);
|
||||
return obj instanceof AnyRequestMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ package org.springframework.security.web.util;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
|
||||
/**
|
||||
@ -36,14 +39,16 @@ import org.springframework.security.web.authentication.DelegatingAuthenticationE
|
||||
*/
|
||||
public class ELRequestMatcher implements RequestMatcher {
|
||||
|
||||
private final org.springframework.security.web.util.matchers.ELRequestMatcher delegate;
|
||||
private final Expression expression;
|
||||
|
||||
public ELRequestMatcher(String el) {
|
||||
delegate = new org.springframework.security.web.util.matchers.ELRequestMatcher(el);
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
expression = parser.parseExpression(el);
|
||||
}
|
||||
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return delegate.matches(request);
|
||||
EvaluationContext context = createELContext(request);
|
||||
return expression.getValue(context, Boolean.class).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,7 +57,7 @@ public class ELRequestMatcher implements RequestMatcher {
|
||||
* @return EL root context which is used to evaluate the expression
|
||||
*/
|
||||
public EvaluationContext createELContext(HttpServletRequest request) {
|
||||
return delegate.createELContext(request);
|
||||
return new StandardEvaluationContext(new ELRequestMatcherContext(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.util;
|
||||
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class ELRequestMatcherContext {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
public ELRequestMatcherContext(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public boolean hasIpAddress(String ipAddress) {
|
||||
return (new IpAddressMatcher(ipAddress).matches(request));
|
||||
}
|
||||
|
||||
public boolean hasHeader(String headerName, String value) {
|
||||
String header = request.getHeader(headerName);
|
||||
if (!StringUtils.hasText(header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.contains(value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package org.springframework.security.web.util;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Matches a request based on IP Address or subnet mask matching against the remote address.
|
||||
* <p>
|
||||
* Both IPv6 and IPv4 addresses are supported, but a matcher which is configured with an IPv4 address will
|
||||
* never match a request which returns an IPv6 address, and vice-versa.
|
||||
*
|
||||
* @deprecated use {@link org.springframework.security.web.util.matchers.IpAddressMatcher}
|
||||
* @author Luke Taylor
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public final class IpAddressMatcher implements RequestMatcher {
|
||||
private final int nMaskBits;
|
||||
private final InetAddress requiredAddress;
|
||||
|
||||
/**
|
||||
* Takes a specific IP address or a range specified using the
|
||||
* IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
|
||||
*
|
||||
* @param ipAddress the address or range of addresses from which the request must come.
|
||||
*/
|
||||
public IpAddressMatcher(String ipAddress) {
|
||||
|
||||
if (ipAddress.indexOf('/') > 0) {
|
||||
String[] addressAndMask = StringUtils.split(ipAddress, "/");
|
||||
ipAddress = addressAndMask[0];
|
||||
nMaskBits = Integer.parseInt(addressAndMask[1]);
|
||||
} else {
|
||||
nMaskBits = -1;
|
||||
}
|
||||
requiredAddress = parseAddress(ipAddress);
|
||||
}
|
||||
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return matches(request.getRemoteAddr());
|
||||
}
|
||||
|
||||
public boolean matches(String address) {
|
||||
InetAddress remoteAddress = parseAddress(address);
|
||||
|
||||
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nMaskBits < 0) {
|
||||
return remoteAddress.equals(requiredAddress);
|
||||
}
|
||||
|
||||
byte[] remAddr = remoteAddress.getAddress();
|
||||
byte[] reqAddr = requiredAddress.getAddress();
|
||||
|
||||
int oddBits = nMaskBits % 8;
|
||||
int nMaskBytes = nMaskBits/8 + (oddBits == 0 ? 0 : 1);
|
||||
byte[] mask = new byte[nMaskBytes];
|
||||
|
||||
Arrays.fill(mask, 0, oddBits == 0 ? mask.length : mask.length - 1, (byte)0xFF);
|
||||
|
||||
if (oddBits != 0) {
|
||||
int finalByte = (1 << oddBits) - 1;
|
||||
finalByte <<= 8-oddBits;
|
||||
mask[mask.length - 1] = (byte) finalByte;
|
||||
}
|
||||
|
||||
// System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
|
||||
|
||||
for (int i=0; i < mask.length; i++) {
|
||||
if ((remAddr[i] & mask[i]) != (reqAddr[i] & mask[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private InetAddress parseAddress(String address) {
|
||||
try {
|
||||
return InetAddress.getByName(address);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Failed to parse address" + address, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,11 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Uses a regular expression to decide whether a supplied the URL of a supplied {@code HttpServletRequest}.
|
||||
*
|
||||
@ -25,13 +30,17 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* by default. Case-insensitive matching can be used by using the constructor which takes the {@code caseInsensitive}
|
||||
* argument.
|
||||
*
|
||||
* @deprecated use {@link org.springframework.security.web.util.matchers.RegexRequestMatcher}
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Rob Winch
|
||||
* @since 3.1
|
||||
* @deprecated use org.springframework.security.web.util.matchers.RegexRequestMatcher
|
||||
*/
|
||||
public final class RegexRequestMatcher implements RequestMatcher {
|
||||
private final org.springframework.security.web.util.matchers.RegexRequestMatcher delegate;
|
||||
private final static Log logger = LogFactory.getLog(RegexRequestMatcher.class);
|
||||
|
||||
private final Pattern pattern;
|
||||
private final HttpMethod httpMethod;
|
||||
|
||||
/**
|
||||
* Creates a case-sensitive {@code Pattern} instance to match against the request.
|
||||
@ -51,7 +60,12 @@ public final class RegexRequestMatcher implements RequestMatcher {
|
||||
* @param caseInsensitive if true, the pattern will be compiled with the {@link Pattern#CASE_INSENSITIVE} flag set.
|
||||
*/
|
||||
public RegexRequestMatcher(String pattern, String httpMethod, boolean caseInsensitive) {
|
||||
this.delegate = new org.springframework.security.web.util.matchers.RegexRequestMatcher(pattern, httpMethod, caseInsensitive);
|
||||
if (caseInsensitive) {
|
||||
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
|
||||
} else {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
}
|
||||
this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,6 +76,31 @@ public final class RegexRequestMatcher implements RequestMatcher {
|
||||
* @return true if the pattern matches the URL, false otherwise.
|
||||
*/
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return delegate.matches(request);
|
||||
if (httpMethod != null && request.getMethod() != null && httpMethod != HttpMethod.valueOf(request.getMethod())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = request.getServletPath();
|
||||
String pathInfo = request.getPathInfo();
|
||||
String query = request.getQueryString();
|
||||
|
||||
if (pathInfo != null || query != null) {
|
||||
StringBuilder sb = new StringBuilder(url);
|
||||
|
||||
if (pathInfo != null) {
|
||||
sb.append(pathInfo);
|
||||
}
|
||||
|
||||
if (query != null) {
|
||||
sb.append('?').append(query);
|
||||
}
|
||||
url = sb.toString();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Checking match of request : '" + url + "'; against '" + pattern + "'");
|
||||
}
|
||||
|
||||
return pattern.matcher(url).matches();
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package org.springframework.security.web.util;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import org.springframework.security.web.util.matchers.ELRequestMatcher;
|
||||
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||
|
||||
/**
|
||||
@ -34,7 +33,7 @@ public class RequestMatcherEditor extends PropertyEditorSupport {
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
setValue(new ELRequestMatcher(text));
|
||||
setValue(new org.springframework.security.web.util.matchers.ELRequestMatcher(text));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -169,17 +169,19 @@ public final class AntPathRequestMatcher implements RequestMatcher {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
org.springframework.security.web.util.matchers.AntPathRequestMatcher other;
|
||||
|
||||
if (obj instanceof org.springframework.security.web.util.AntPathRequestMatcher) {
|
||||
other = ((org.springframework.security.web.util.AntPathRequestMatcher) obj).getDelegate();
|
||||
org.springframework.security.web.util.AntPathRequestMatcher other = (org.springframework.security.web.util.AntPathRequestMatcher) obj;
|
||||
return this.pattern.equals(other.getPattern()) &&
|
||||
this.httpMethod == other.getHttpMethod() &&
|
||||
this.caseSensitive == other.isCaseSensitive();
|
||||
} else if(obj instanceof AntPathRequestMatcher) {
|
||||
other = (AntPathRequestMatcher) obj;
|
||||
} else {
|
||||
return false;
|
||||
org.springframework.security.web.util.matchers.AntPathRequestMatcher other = (AntPathRequestMatcher) obj;
|
||||
return this.pattern.equals(other.pattern) &&
|
||||
this.httpMethod == other.httpMethod &&
|
||||
this.caseSensitive == other.caseSensitive;
|
||||
}
|
||||
return this.pattern.equals(other.pattern) &&
|
||||
this.httpMethod == other.httpMethod &&
|
||||
this.caseSensitive == other.caseSensitive;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user