gpt4 book ai didi

spring-mvc - 如何将 Spring DelegatingFilterProxy 与多个过滤器和 Spring Security 一起使用?

转载 作者:行者123 更新时间:2023-12-05 07:55:13 28 4
gpt4 key购买 nike

我们正在使用使用 AbstractSecurityWebApplicationInitializer 初始化的 Spring 安全性。我们还有一个单独的 Web 应用初始化程序,它从 AbstractAnnotationConfigDispatcherServletInitializer 扩展而来。按照前者的 Javadoc 中的建议,我将后者设为 @Order(Ordered.HIGHEST_PRECEDENCE)。到目前为止一切顺利。

现在我想介绍额外的 Servlet 过滤器,它们与 Spring 安全性无关,因此应该单独配置。我知道我可以使用 DelegatingFilterProxy 将请求委托(delegate)给过滤器。但是 DelegatingFilterProxy 没有接受多个过滤器的能力。一种选择是定义自定义 FilterChain,如 Spring Security FilterChainProxy 中所做的那样。这仍然会创建 2 个 DelegatingFilterProxy,我知道应用程序中应该只有一个 DelegatingFilterProxy

有什么想法吗?

最佳答案

回答我自己的问题,我是这样做的:

我将 AbstractAnnotationConfigDispatcherServletInitializer 子类化并在其中:

/**
* {@inheritDoc}
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[] { requestContextFilter(), teFilterChain() };
}

/**
* {@inheritDoc}
*/
@Override
protected FilterRegistration.Dynamic registerServletFilter(
ServletContext servletContext, Filter filter) {
String filterName = Conventions.getVariableName(filter);
Dynamic registration = servletContext.addFilter(filterName, filter);
if (registration == null) {
int counter = -1;
while (counter == -1 || registration == null) {
counter++;
registration = servletContext
.addFilter(filterName + "#" + counter, filter);
Assert.isTrue(counter < 100, "Failed to register filter '"
+ filter + "'."
+ "Could the same Filter instance have been registered already?");
}
}
registration.setAsyncSupported(isAsyncSupported());

registration.addMappingForServletNames(getDispatcherTypes(), false,
getServletName());
return registration;
}

/**
* Spring, by default, registers filters for 'FORWARD' dispatcher type as
* well which causes TE filter chain to run again after Spring security
* successfully authenticates and forwards the incoming request. We thus
* exclude 'FORWARD' dispatcher type.
*/
private EnumSet<DispatcherType> getDispatcherTypes() {
return (isAsyncSupported()
? EnumSet.of(DispatcherType.REQUEST, DispatcherType.INCLUDE,
DispatcherType.ASYNC)
: EnumSet.of(DispatcherType.REQUEST, DispatcherType.INCLUDE));
}

private Filter requestContextFilter() {
return new DelegatingFilterProxy(TE_REQ_CTX_FILTER);
}

private Filter teFilterChain() {
return new DelegatingFilterProxy(TE_FILTER_CHAIN);
}

@Override
protected void registerDispatcherServlet(ServletContext ctx) {
super.registerDispatcherServlet(ctx);

registerSpringSecurityFilter(ctx);
registerCorsFilter(ctx);
}

@Override
protected DispatcherServlet createDispatcherServlet(
WebApplicationContext servletAppContext) {
DispatcherServlet servlet = new DispatcherServlet(servletAppContext);
servlet.setThreadContextInheritable(true);
servlet.setThrowExceptionIfNoHandlerFound(true);

return servlet;
}

private Dynamic registerCorsFilter(ServletContext ctx) {
Dynamic registration = ctx.addFilter("CorsFilter", CorsFilter.class);

registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_ORIGINS,
CORS_ALLOWED_ORIGINS);
registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_METHODS,
CORS_ALLOWED_METHODS);
registration.setInitParameter(CorsFilter.PARAM_CORS_ALLOWED_HEADERS,
CORS_ALLOWED_HEADERS);

registration.addMappingForUrlPatterns(getDispatcherTypes(), false,
"/*");

return registration;
}

@Override
protected boolean isAsyncSupported() {
return true;
}

private final FilterRegistration.Dynamic registerSpringSecurityFilter(
ServletContext servletContext) {
FilterRegistration.Dynamic registration = servletContext.addFilter(
SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain());

if (registration == null) {
throw new IllegalStateException("Duplicate Filter registration for "
+ SPRING_SECURITY_FILTER_CHAIN
+ "'. Check to ensure the Filter is only configured once.");
}

registration.setAsyncSupported(isAsyncSupported());
EnumSet<DispatcherType> dispatcherTypes = getSecurityDispatcherTypes();
/*
* Don't use URL mapping for registering Spring security because then
* the chain will kick in before DispatcherServlet.
*/
registration.addMappingForServletNames(dispatcherTypes, true,
getServletName());

return registration;
}

private Filter springSecurityFilterChain() {
return new DelegatingFilterProxy(SPRING_SECURITY_FILTER_CHAIN);
}

protected EnumSet<DispatcherType> getSecurityDispatcherTypes() {
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR,
DispatcherType.ASYNC);
}

关于spring-mvc - 如何将 Spring DelegatingFilterProxy 与多个过滤器和 Spring Security 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30200841/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com