跨源请求阻止Spring REST服务+ AJAX

无法调用spring REST服务

我的春季服务

@RequestMapping(value = "/MAS/authenticate", method = RequestMethod.POST) public ResponseEntity<Map> authenticate(@RequestBody Subject subject) { Map result = new HashMap(); result.put("result_detail", "Invalid Password"); result.put("result", "failure"); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentType(MediaType.APPLICATION_JSON); responseHeaders.add("Access-Control-Allow-Origin", "*"); // also added header to allow cross domain request for any domain return new ResponseEntity<Map>(result, responseHeaders, HttpStatus.OK); } 

我的AJAX代码

 $.ajax( { crossDomain: true, type: "POST", contentType: "application/json; charset=utf-8", async: false, url: "http://localhost:8080/SpringMVC/rest/MAS/authenticate", headers: {"Access-Control-Allow-Origin" : "*"}, data:{}, dataType: "json", //also tried "jsonp" success: function(data, status, jqXHR) { alert('success'); }, error: function(jqXHR, status) { alert('error'); } }); 

我收到以下错误:(

跨源请求已阻止:同源策略禁止在http:// localhost:8080 / SpringMVC / rest / MAS / authenticate中读取远程资源。 这可以通过将资源移动到同一域或启用CORS来解决。

我也试过dataType: "jsonp" 。 它将我的body对象附加到URL中,该URL生成不同的URL,然后无法点击我的服务URL,并得到404错误。

我的浏览器:firefox 36.0.4

我如何摆脱这个错误,任何帮助?

我的AJAX通话和服务都没问题。 在互联网上搜索了很多,我发现它的服务器端问题不是客户端。

在Spring的服务器端,我们必须实现允许CORS请求的filter。

filter看起来像这样。

 import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.filter.OncePerRequestFilter; public class CORSFilter extends OncePerRequestFilter { private static final Log LOG = LogFactory.getLog(CORSFilter.class); @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())) { LOG.trace("Sending Header...."); // CORS "pre-flight" request response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); // response.addHeader("Access-Control-Allow-Headers", "Authorization"); response.addHeader("Access-Control-Allow-Headers", "Content-Type"); response.addHeader("Access-Control-Max-Age", "1"); } filterChain.doFilter(request, response); } } 

并在web.xml中将此filter应用于您的服务请求

   cors com.test.common.controller.CORSFilter    cors /*  

这可能有助于遇到此问题的其他人。 🙂

默认情况下,唯一允许的方法是GET ,并且您不允许服务器端的POST

 Access-Control-Allow-Origin: * 

此标头仅启用CORS,但您需要添加以下内容:

 Access-Control-Allow-Methods: POST, GET 

有关 Mozilla项目的HTTP access control (CORS)更详细的操作方法

所以你的代码应该是这样的:

 responseHeaders.add("Access-Control-Allow-Methods", "POST, GET"); // also added header to allow POST, GET method to be available responseHeaders.add("Access-Control-Allow-Origin", "*"); // also added header to allow cross domain request for any domain 

更新

我重新阅读了这篇文章,并找到了一些细节:

一个简单的跨站点请求是:

  • 仅使用GET,HEAD或POST。 如果使用POST将数据发送到服务器,则使用HTTP POST请求发送到服务器的数据的Content-Type是application / x-www-form-urlencoded,multipart / form-data或text / plain之一。
  • 不使用HTTP请求设置自定义标头(例如X-Modified等)

您可以用粗体显示,您必须为您的数据设置其他Content-Type (目前它是contentType: "application/json; charset=utf-8", )或使用后面描述的预检技术:

  • 它使用GET,HEAD或POST以外的方法。 此外,如果使用POST来发送具有除application / x-www-form-urlencoded,multipart / form-data或text / plain之外的Content-Type的请求数据,例如,如果POST请求将XML有效负载发送到服务器使用application / xml或text / xml,请求预检。
  • 它在请求中设置自定义标头 (例如,请求使用诸如X-PINGOTHER之类的标头)

因此,我建议您更改contentType或尝试将此标头用于您的请求:

 Access-Control-Request-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE 

并将此标题添加到您的回复中:

 Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE 

然后,您可以尝试调用您的方法。

以下是跨平台spring boot Web服务调用的解决方案。

应用程序URL: http:// localhost:8080

Webservice URL: http:// localhost:9090

在弹簧控制器中使用以下注释

 @CrossOrigin(origins = "http://localhost:8080") @RequestMapping(value = "/uri", method = RequestMethod.GET) public SomeObject someMethod(){ // your logic will come here }