自动为每个响应添加标头

时间:2013-04-24 11:23:50

标签: spring spring-mvc cors response-headers

我想在我的应用程序中为休息控制器提出请求以允许跨源资源共享时,将此标头“Access-Control-Allow-Origin”,“*”添加到客户端的每个响应中当前我是手动将此标题添加到每个方法,如此

HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Allow-Origin", "*");

它的工作但非常令人沮丧。我在spring docs中找到了webContentInterceptor,它允许我们修改每个响应的标题

<mvc:interceptors>
<bean id="webContentInterceptor" 
class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="Access-Control-Allow-Origin" value="*"/>
</bean>
</mvc:interceptors>

但是当我使用它时会抛出错误,找不到名称为Access-Control-Allow-Origin的属性,所以我们可以自动为每个响应添加标头

更新! Spring框架4.2通过将@CrossOrigin注释添加到方法或控制器本身https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

来大大简化了这一点。

6 个答案:

答案 0 :(得分:57)

我最近遇到了这个问题并找到了这个解决方案。 您可以使用过滤器添加这些标头:

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
            response.addHeader("Access-Control-Allow-Origin", "*");
            if (request.getHeader("Access-Control-Request-Method") != null
                    && "OPTIONS".equals(request.getMethod())) {
                // CORS "pre-flight" request
                response.addHeader("Access-Control-Allow-Methods",
                        "GET, POST, PUT, DELETE");
                response.addHeader("Access-Control-Allow-Headers",
                        "X-Requested-With,Origin,Content-Type, Accept");
            }
            filterChain.doFilter(request, response);
    }

}

不要忘记将过滤器添加到弹簧上下文中:

<bean id="corsFilter" class="my.package.CorsFilter" />

和web.xml中的映射:

<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

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

为了更进一步,您可以指定一个Spring配置文件来启用或禁用此过滤器:

<beans profile="!cors">
    <bean id="corsFilter" class="my.package.FilterChainDoFilter" />
</beans>

<beans profile="cors">
    <bean id="corsFilter" class="my.package.CorsFilter" />
</beans>

(提供类似于CorsFilter的FilterChainDoFilter,但只在doFilterInternal(..)中执行filterChain.doFilter(request, response);

答案 1 :(得分:15)

更新! Spring框架4.2通过将@CrossOrigin注释添加到方法或控制器本身来大大简化了这一过程 https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

答案 2 :(得分:5)

如果要为控制器设置标题,可以使用@ModelAttribute注释。

@ModelAttribute
public void setVaryResponseHeader(HttpServletResponse response) {
    response.setHeader("Vary", "Accept");
}    

答案 3 :(得分:1)

在Spring 4中,您可以使用@CrossOrigin() 它允许你跨越原点问题。

出于安全原因,浏览器禁止对驻留在当前源外的资源进行AJAX调用。例如,当您在一个标签中检查您的银行帐户时,您可以将evil.com网站放在另一个标签中。来自evil.com的脚本不能使用您的凭据向您的银行API发送AJAX请求(从您的帐户中提取资金!)。

跨域资源共享(CORS)是大多数浏览器实现的W3C规范,允许您以灵活的方式指定授权的跨域请求类型,而不是使用IFrame等较不安全且功能较弱的黑客攻击或JSONP。

Spring Framework 4.2 GA为开箱即用的CORS提供了一流的支持,为您提供了比典型的基于过滤器的解决方案更简单,更强大的配置方式。

您可以在@RequestMapping带注释的处理程序方法中添加@CrossOrigin注释,以便在其上启用CORS。默认情况下,@ CrossOrigin允许@RequestMapping注释中指定的所有原点和HTTP方法:

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html

https://spring.io/guides/gs/rest-service-cors/

https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

答案 4 :(得分:0)

WebContentInterceptor没有名为Access-Control-Allow-Origin的属性,据我所知,它没有公开任何设置响应标头的方法。它只通过启用/禁用某些属性来设置一些与缓存相关的标头。但是编写自己的拦截器(或servlet过滤器)可以做到这一点很简单。

答案 5 :(得分:0)

我也遇到了这个问题,我已经修复了这个代码问题。

public static HttpServletResponse getResponse(HttpServletResponse response) {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setCharacterEncoding("UTF-8");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    return response;
}