Spring Security Config : HttpSecurity安全配置器 RequestCacheConfigurer

本文详细介绍了在Spring Security中如何配置HttpSecurity的RequestCacheConfigurer,包括RequestCache的设置流程,安全过滤器RequestCacheAwareFilter的配置,以及针对特定请求不进行缓存的规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

介绍

作为一个配置HttpSecuritySecurityConfigurer,RequestCacheConfigurer的配置任务如下 :

  • 配置如下安全过滤器Filter
    • RequestCacheAwareFilter
      • 属性RequestCache requestCache 的设置流程如下 :
          1. 首先尝试从共享对象获取
          1. 其次尝试从bean IoC容器获取
          1. 最后尝试使用缺省值 HttpSessionRequestCache
          • 针对以下几种情况之外的请求不会被缓存
            • /**/favicon.*
            • XMLHttpRequest
            • application/json
          • GET /**csrf保护开启时请求也不会被缓存

继承关系

RequestCacheConfigurer

使用

    // HttpSecurity 代码片段
    public RequestCacheConfigurer<HttpSecurity> requestCache() throws Exception {
		return getOrApply(new RequestCacheConfigurer<>());
	}

源代码

源代码版本 Spring Security Config 5.1.4.RELEASE

package org.springframework.security.config.annotation.web.configurers;

// 省略 imports


public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>> extends
		AbstractHttpConfigurer<RequestCacheConfigurer<H>, H> {

	public RequestCacheConfigurer() {
	}

	/**
	 * Allows explicit configuration of the RequestCache to be used. Defaults to
	 * try finding a RequestCache as a shared object. Then falls back to a
	 * HttpSessionRequestCache.
	 *
	 * @param requestCache the explicit RequestCache to use
	 * @return the RequestCacheConfigurer for further customization
	 */
	public RequestCacheConfigurer<H> requestCache(RequestCache requestCache) {
		getBuilder().setSharedObject(RequestCache.class, requestCache);
		return this;
	}

	@Override
	public H disable() {
		getBuilder().setSharedObject(RequestCache.class, new NullRequestCache());
		return super.disable();
	}

	@Override
	public void init(H http) throws Exception {
		http.setSharedObject(RequestCache.class, getRequestCache(http));
	}

	@Override
	public void configure(H http) throws Exception {
		// 创建  RequestCache
		RequestCache requestCache = getRequestCache(http);
		// 创建  RequestCacheAwareFilter
		RequestCacheAwareFilter requestCacheFilter = new RequestCacheAwareFilter(
				requestCache);
		requestCacheFilter = postProcess(requestCacheFilter);
		http.addFilter(requestCacheFilter);
	}

	/**
	 * Gets the RequestCache to use. If one is defined using
	 * #requestCache(org.springframework.security.web.savedrequest.RequestCache),
	 * then it is used. Otherwise, an attempt to find a RequestCache shared object
	 * is made. If that fails, an HttpSessionRequestCache is used
	 *
	 * @param http the HttpSecurity to attempt to fined the shared object
	 * @return the RequestCache to use
	 */
	private RequestCache getRequestCache(H http) {
		// 首先尝试从共享对象获取 RequestCache
		RequestCache result = http.getSharedObject(RequestCache.class);
		if (result != null) {
			return result;
		}
        
		// 其次尝试从bean容器中获取 RequestCache 
		result = getBeanOrNull(RequestCache.class);
		if (result != null) {
			return result;
		}
        
		// 最后尝试使用缺省 RequestCache :  HttpSessionRequestCache
		HttpSessionRequestCache defaultCache = new HttpSessionRequestCache();
		defaultCache.setRequestMatcher(createDefaultSavedRequestMatcher(http));
		return defaultCache;
	}

	private <T> T getBeanOrNull(Class<T> type) {
		ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
		if (context == null) {
			return null;
		}
		try {
			return context.getBean(type);
		} catch (NoSuchBeanDefinitionException e) {
			return null;
		}
	}
	@SuppressWarnings("unchecked")
	private RequestMatcher createDefaultSavedRequestMatcher(H http) {
		ContentNegotiationStrategy contentNegotiationStrategy = http
				.getSharedObject(ContentNegotiationStrategy.class);
		if (contentNegotiationStrategy == null) {
			contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
		}

		RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher(
				"/**/favicon.*"));

		MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(
				contentNegotiationStrategy, MediaType.APPLICATION_JSON);
		jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
		RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest);

		RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
				new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));

		boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;

		List<RequestMatcher> matchers = new ArrayList<>();
		if (isCsrfEnabled) {
			RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET");
			matchers.add(0, getRequests);
		}
		matchers.add(notFavIcon);
		matchers.add(notJson);
		matchers.add(notXRequestedWith);

		return new AndRequestMatcher(matchers);
	}
}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值