欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring 小计 Spring 

程序员文章站 2022-06-12 12:18:00
...

FilterInvocationMetadataSource

public class FilterInvocationSecurityMetadataSourceImpl implements
		FilterInvocationSecurityMetadataSource {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	// 默认使用AntUrlPathMatcher
	private UrlMatcher urlMatcher;

	private boolean stripQueryStringFromUrls;

	private static final Set<String> HTTP_METHODS = new HashSet<String>(
			Arrays.asList("DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT",
					"TRACE"));

	/**
	 * Stores request maps keyed by specific HTTP methods. A null key matches
	 * any method
	 */
	private Map<String, Map<Object, Collection<ConfigAttribute>>> httpMethodMap = new HashMap<String, Map<Object, Collection<ConfigAttribute>>>();

	@Autowired
	public FilterInvocationSecurityMetadataSourceImpl(
			SecurityMetadataConverter adapter) {
		urlMatcher = new AntUrlPathMatcher();

//		LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestMap = adapter.getRequestMap();
//		for (Map.Entry<RequestKey, Collection<ConfigAttribute>> entry : requestMap
//				.entrySet()) {
//			addSecureUrl(entry.getKey().getUrl(), entry.getKey().getMethod(),
//					entry.getValue());
//		}
		Collection<Config> configs = adapter.configs();
		for(Config config:configs){
			//logger.info("{}",config.getAttributes());
			addSecureUrl(config.getPath(),null,config.getAttributes());
		}
	}

	// ~ Methods
	// ========================================================================================================

	/**
	 * Adds a URL,attribute-list pair to the request map, first allowing the
	 * <tt>UrlMatcher</tt> to process the pattern if required, using its
	 * <tt>compile</tt> method. The returned object will be used as the key to
	 * the request map and will be passed back to the <tt>UrlMatcher</tt> when
	 * iterating through the map to find a match for a particular URL.
	 */
	private void addSecureUrl(String pattern, String method,
			Collection<ConfigAttribute> attrs) {
		//
		Map<Object, Collection<ConfigAttribute>> mapToUse = getRequestMapForHttpMethod(method);

		mapToUse.put(urlMatcher.compile(pattern), attrs);
		//attrs.toArray(new ConfigAttribute[] {})[0].getAttribute();
		if (logger.isDebugEnabled()) {
			logger.debug("Added URL pattern: "
					+ pattern
					+ "; attributes: "
					+ attrs
					+ (method == null ? "" : " for HTTP method '" + method
							+ "'"));
		}
	}

	/**
	 * Return the HTTP method specific request map, creating it if it doesn't
	 * already exist.
	 * 
	 * @param method
	 *            GET, POST etc
	 * @return map of URL patterns to <tt>ConfigAttribute</tt>s for this method.
	 */
	private Map<Object, Collection<ConfigAttribute>> getRequestMapForHttpMethod(
			String method) {
		if (method != null && !HTTP_METHODS.contains(method)) {
			throw new IllegalArgumentException("Unrecognised HTTP method: '"
					+ method + "'");
		}

		// 用Http Method当作key,value是一个Http Url 
		Map<Object, Collection<ConfigAttribute>> methodRequestMap = httpMethodMap
				.get(method);

		if (methodRequestMap == null) {
			methodRequestMap = new LinkedHashMap<Object, Collection<ConfigAttribute>>();
			httpMethodMap.put(method, methodRequestMap);
		}

		return methodRequestMap;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();

		for (Map.Entry<String, Map<Object, Collection<ConfigAttribute>>> entry : httpMethodMap
				.entrySet()) {
			for (Collection<ConfigAttribute> attrs : entry.getValue().values()) {
				allAttributes.addAll(attrs);
			}
		}

		return allAttributes;
	}

	public Collection<ConfigAttribute> getAttributes(Object object) {
		if ((object == null) || !this.supports(object.getClass())) {
			throw new IllegalArgumentException(
					"Object must be a FilterInvocation");
		}

		String url = ((FilterInvocation) object).getRequestUrl();
		String method = ((FilterInvocation) object).getHttpRequest()
				.getMethod();

		return lookupAttributes(url, method);
	}

	/**
	 * Performs the actual lookup of the relevant <tt>ConfigAttribute</tt>s for
	 * the given <code>FilterInvocation</code>.
	 * <p>
	 * By default, iterates through the stored URL map and calls the
	 * {@link UrlMatcher#pathMatchesUrl(Object path, String url)} method until a
	 * match is found.
	 * 
	 * @param url
	 *            the URI to retrieve configuration attributes for
	 * @param method
	 *            the HTTP method (GET, POST, DELETE...), or null for any
	 *            method.
	 * 
	 * @return the <code>ConfigAttribute</code>s that apply to the specified
	 *         <code>FilterInvocation</code> or null if no match is found
	 */
	public final Collection<ConfigAttribute> lookupAttributes(String url,
			String method) {
		if (stripQueryStringFromUrls) {
			// Strip anything after a question mark symbol, as per SEC-161. See
			// also SEC-321
			int firstQuestionMarkIndex = url.indexOf("?");

			if (firstQuestionMarkIndex != -1) {
				url = url.substring(0, firstQuestionMarkIndex);
			}
		}

		if (urlMatcher.requiresLowerCaseUrl()) {
			url = url.toLowerCase();

			if (logger.isDebugEnabled()) {
				logger.debug("Converted URL to lowercase, from: '" + url
						+ "'; to: '" + url + "'");
			}
		}

		// Obtain the map of request patterns to attributes for this method and
		// lookup the url.
		Collection<ConfigAttribute> attributes = extractMatchingAttributes(url,
				httpMethodMap.get(method));

		// If no attributes found in method-specific map, use the general one
		// stored under the null key
		if (attributes == null) {
			attributes = extractMatchingAttributes(url, httpMethodMap.get(null));
		}

		return attributes;
	}

	private Collection<ConfigAttribute> extractMatchingAttributes(String url,
			Map<Object, Collection<ConfigAttribute>> map) {
		if (map == null) {
			return null;
		}

		final boolean debug = logger.isDebugEnabled();

		for (Map.Entry<Object, Collection<ConfigAttribute>> entry : map
				.entrySet()) {
			Object p = entry.getKey();
			boolean matched = urlMatcher.pathMatchesUrl(entry.getKey(), url);

			if (debug) {
				logger.debug("Candidate is: '" + url + "'; pattern is " + p
						+ "; matched=" + matched);
			}

			if (matched) {
				return entry.getValue();
			}
		}
		return null;
	}

	public boolean supports(Class<?> clazz) {
		return FilterInvocation.class.isAssignableFrom(clazz);
	}

	protected UrlMatcher getUrlMatcher() {
		return urlMatcher;
	}

	public boolean isConvertUrlToLowercaseBeforeComparison() {
		return urlMatcher.requiresLowerCaseUrl();
	}

	public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
		this.stripQueryStringFromUrls = stripQueryStringFromUrls;
	}
}
 
相关标签: Spring