使用 Spring 3.0.4 启用 Cors

Posted

技术标签:

【中文标题】使用 Spring 3.0.4 启用 Cors【英文标题】:Enable Cors using Spring 3.0.4 【发布时间】:2019-08-17 04:39:03 【问题描述】:

我正在使用 Java Spring 3.0.4(由于某些要求无法升级),我需要启用 Cors 以便前端与后端通信。

我的后端是一个 Angular 应用程序,运行在:http://localhost:4200/home

我尝试了以下方法,但没有成功:

public static final String CREDENTIALS_NAME = "Access-Control-Allow-Credentials";
public static final String ORIGIN_NAME = "Access-Control-Allow-Origin";
public static final String METHODS_NAME = "Access-Control-Allow-Methods";
public static final String HEADERS_NAME = "Access-Control-Allow-Headers";
public static final String MAX_AGE_NAME = "Access-Control-Max-Age";

@PreAuthorize("hasRole('ADMIN')")
@RequestMapping(value="/data", method=RequestMethod.GET)
public void serverSide(Model model,  HttpServletRequest request, HttpServletResponse response) throws IOException

    response.setContentType("application/json");
    response.setHeader("Cache-Control", "no-store");

    response.setHeader(CREDENTIALS_NAME, "true");
    response.setHeader(ORIGIN_NAME, "http://localhost:4200");
    response.setHeader(METHODS_NAME, "GET, OPTIONS, POST, PUT, DELETE");
    response.setHeader(HEADERS_NAME, "Origin, X-Requested-With, Content-Type, Accept");
    response.setHeader(MAX_AGE_NAME, "3600");

    PrintWriter out = response.getWriter();

    out.print("TEST!!");
       

【问题讨论】:

你试过在控制器方法上添加@CrossOrigin吗? 我相信注释是在 Spring 3.2 中添加的,但是是的,我已经尝试过了,它抱怨注释没有定义。 @MadhuBhat 您是否有机会运行 Apache Tomcat?您是如何部署应用的? @KarolDowbecki 是的,我正在运行 Apache Tomcat,但我不太确定我们的应用程序是如何部署的(对于这个团队来说非常新) @sbattou 你可以在这里尝试任何答案***.com/questions/32319396/… 吗? 【参考方案1】:

您可以扩展Filter 接口。

public class CORSFilter implements Filter 

  @Override
  public void init(FilterConfig filterConfig) throws ServletException 

  

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
      HttpServletResponse httpResponse = (HttpServletResponse) response;
      httpResponse.addHeader("Access-Control-Allow-Origin", "*");
      httpResponse.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, OPTIONS");
      httpResponse.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");       chain.doFilter(request, response);
  

  @Override
  public void destroy() 

  

然后你需要在web.xml注册过滤器

<filter>
    <filter-name>cors</filter-name>
    <filter-class>com.yourpackage.CORSFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>cors</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

【讨论】:

我真的很感激,我是否必须从我的控制器中调用 CorsFilter 类,或者 web.xml 文件基本上会将它应用于任何 CRUD 操作? 它应该适用于该网络应用程序中的每个 URL,因为过滤器映射到 /* URL。 仍然出现错误 SEC7120: Origin localhost:4200 not found in Access-Control-Allow-Origin 标头。我真的认为这会奏效,还有其他建议吗? 尝试用"Access-Control-Allow-Origin", "http://localhost:4200"替换"Access-Control-Allow-Origin", "*" 原来有一段代码正在重定向我的请求,一旦我禁用它一切正常!【参考方案2】:

您可以通过创建拦截器来启用 CORS。请按照以下步骤操作:

    通过扩展HandlerInterceptorAdapter创建拦截器

    public class CorsInterceptor extends HandlerInterceptorAdapter 
    
        public static final String CREDENTIALS_NAME = "Access-Control-Allow-Credentials";
        public static final String ORIGIN_NAME = "Access-Control-Allow-Origin";
        public static final String METHODS_NAME = "Access-Control-Allow-Methods";
        public static final String HEADERS_NAME = "Access-Control-Allow-Headers";
        public static final String MAX_AGE_NAME = "Access-Control-Max-Age";
    
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
          Object handler) throws Exception 
          response.setHeader(CREDENTIALS_NAME, "true");
          response.setHeader(ORIGIN_NAME, "http://localhost:4200");
          response.setHeader(METHODS_NAME, "GET, OPTIONS, POST, PUT, DELETE");
          response.setHeader(HEADERS_NAME, "Origin, X-Requested-With, Content-Type, 
            Accept");
          response.setHeader(MAX_AGE_NAME, "3600");
          return true;
      
    
    
    

    在您的 Web 配置中注册上面创建的拦截器。

    public class WebConfig extends WebMvcConfigurerAdapter 
    
      @Override
      public void addInterceptors(InterceptorRegistry registry) 
        registry.addInterceptor(new CorsInterceptor());
      
     // continue if any ..
    
    

    以上对于 GET 请求工作正常,但对于任何其他修改请求(POST、DELETE、PUT),浏览器将发送 SpringMVC 忽略的预检 OPTIONS 请求。因此,您必须发送 Options 请求。您可以在 web.xml 上添加 dispatchOptionRequest,如下所示:

    <servlet>
        <servlet-name>servletName</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
         <param-name>dispatchOptionsRequest</param-name>
         <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    

希望这会有所帮助! 谢谢。

【讨论】:

感谢您抽出宝贵时间发布答案。是否因为我的应用程序中似乎没有 Web 配置类而创建 Web 配置类? 我仍在使用 Spring 3.0.5,是否需要在 xml 文件中的任何位置添加“CorsInterceptor”或“WebConfig”作为配置,否则 Spring 会在启动时自动加载这些类?【参考方案3】:

使用 WebMVC 是可能的,并且对我有用。 试试这个,但如果你使用 spring security 我可能需要更新答案

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfiguration implements WebMvcConfigurer 

private static final String HTTP_LOCALHOST_4200 = "http://localhost:4200";
private static final String GET = "GET";
private static final String POST = "POST";
private static final String PUT = "PUT";
private static final String DELETE = "DELETE";
private static final String HEAD = "HEAD";

@Override
public void addCorsMappings(CorsRegistry registry) 

    registry.addMapping("/**")
            .allowedOrigins(
                    HTTP_LOCALHOST_4200).allowedMethods(GET, POST, PUT, DELETE, 
  HEAD).allowCredentials(true);
 
 

【讨论】:

CorsConfiguration 在 spring 3.0 中不可用 addCorsMappings 自春季 4.2 起

以上是关于使用 Spring 3.0.4 启用 Cors的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 3.0.4 is available now!

使用 spring 启用 WebSockets

如何在 Spring Boot 中使用 Spring Security 启用 CORS

如何解决在使用 Spring Boot 和 Spring Security 启用 CSRF 后无法正常工作的登录问题?

如何使用 Spring MVC 和 Spring Security 为资源处理程序启用 HTTP 缓存

如何在 Spring Boot 中在 Spring Security 级别启用 CORS [关闭]