跨源请求阻止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 }