سؤال

I want to add this header "Access-Control-Allow-Origin", "*" to every response made to the client whenever a request has made for rest controllers in my application to allow cross origin resource sharing Currently I 'm manually adding this header to each and every method like this

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

Its working but its very frustrating . I found webContentInterceptor in spring docs which allow us to modify headers on each response

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

but when i use this it throws error that property not found of name Access-Control-Allow-Origin so is there any other way we can automatically add header to every response

Update ! Spring framework 4.2 greatly simplifies this by adding @CrossOrigin annotation to either a method or a controller itself https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

هل كانت مفيدة؟

المحلول

I recently got into this issue and found this solution. You can use a filter to add these headers :

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);
    }

}

Don't forget add the filter to your spring context:

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

and the mapping in the 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>

To go a little further you can specify a Spring profile to enable or disable this filter with something like that:

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

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

(providing the FilterChainDoFilter similar to the CorsFilter but which only does filterChain.doFilter(request, response); in the doFilterInternal(..))

نصائح أخرى

Update ! Spring framework 4.2 greatly simplifies this by adding @CrossOrigin annotation to either a method or a controller itself https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

If you want to set headers for controller you can use @ModelAttribute annotation.

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

In the Spring 4, You can use the @CrossOrigin() which allows you the cross origin issue.

For security reasons, browsers prohibit AJAX calls to resources residing outside the current origin. For example, as you’re checking your bank account in one tab, you could have the evil.com website in another tab. The scripts from evil.com shouldn’t be able to make AJAX requests to your bank API (withdrawing money from your account!) using your credentials.

Cross-origin resource sharing (CORS) is a W3C specification implemented by most browsers that allows you to specify in a flexible way what kind of cross domain requests are authorized, instead of using some less secured and less powerful hacks like IFrame or JSONP.

Spring Framework 4.2 GA provides first class support for CORS out-of-the-box, giving you an easier and more powerful way to configure it than typical filter based solutions.

You can add an @CrossOrigin annotation to your @RequestMapping annotated handler method in order to enable CORS on it. By default @CrossOrigin allows all origins and the HTTP methods specified in the @RequestMapping annotation:

@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

WebContentInterceptor doesn't have a property named Access-Control-Allow-Origin, and as far as I can see, it does not expose any methods for setting response headers. It only sets some cache related headers by enabling/disabling some properties. But it's trivial to write your own interceptor (or servlet filter) that does this.

I am also face this issue and i have add this code issue fixed.

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;
}

Basically, I was facing a block in the Browser because my Spring Server was not telling the Browser what to do (Not adding "Allowed Origins" in the Header).

So, what has solved in SPRING CLOUD GATEWAY was what follows:

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomGlobalFilter implements GlobalFilter {


@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    exchange.getResponse().getHeaders().set("Access-Control-Allow-Origin", "*");

    if (exchange.getResponse().getHeaders().getAccessControlRequestMethod() != null
            && "OPTIONS".equals(exchange.getResponse().getHeaders().getAccessControlRequestMethod())) {
        // CORS "pre-flight" request
        exchange.getResponse().getHeaders().set("Access-Control-Allow-Methods",
                "GET, POST, PUT, DELETE");
        exchange.getResponse().getHeaders().set("Access-Control-Allow-Headers",
                "X-Requested-With,Origin,Content-Type,Accept");
    }
    return chain.filter(exchange);
}

}

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top