javascript 跨域请求阻塞 Spring REST 服务 + AJAX
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29389031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-Origin Request Blocked Spring REST service + AJAX
提问by Muhammad Suleman
Unable to call spring REST service
无法调用 spring REST 服务
My spring service
我的春季服务
@RequestMapping(value = "/MAS/authenticate", method = RequestMethod.POST)
public ResponseEntity<Map<String, String>> authenticate(@RequestBody Subject subject) {
Map<String, String> result = new HashMap<String, String>();
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<String, String>>(result, responseHeaders, HttpStatus.OK);
}
My AJAX code
我的 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');
}
});
I am getting following error :(
我收到以下错误:(
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/SpringMVC/rest/MAS/authenticate. This can be fixed by moving the resource to the same domain or enabling CORS.
跨域请求被阻止:同源策略不允许在http://localhost:8080/SpringMVC/rest/MAS/authenticate读取远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。
i have also tried dataType: "jsonp"
. its append my body object into URL which make different URL and cannot hit my service URL then and got 404 error.
我也试过了dataType: "jsonp"
。它将我的正文对象附加到 URL 中,该 URL 生成不同的 URL,然后无法访问我的服务 URL 并出现 404 错误。
My browser: firefox 36.0.4
我的浏览器:firefox 36.0.4
How i can get rid from this error, any help?
我怎样才能摆脱这个错误,有什么帮助吗?
回答by Muhammad Suleman
My AJAX call and service were OK. After searching a lot on internet i have found that its server side problem not client side.
我的 AJAX 调用和服务还可以。在互联网上搜索了很多之后,我发现它的服务器端问题不是客户端。
on server side with Spring we have to implement filter which will allow CORS requests.
在使用 Spring 的服务器端,我们必须实现允许 CORS 请求的过滤器。
filter will look like this.
过滤器看起来像这样。
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);
}
}
and in web.xml apply this filter on your service requests like this
并在 web.xml 中将此过滤器应用于您的服务请求,如下所示
<filter>
<filter-name>cors</filter-name>
<filter-class>com.test.common.controller.CORSFilter</filter-class> <!-- your package name and filter class -->
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This may help someone else who went through this problem. :)
这可能会帮助遇到此问题的其他人。:)
回答by VMAtm
By default the only method allowed is a GET
, and you don't allow the POST
on your server side:
默认情况下,唯一允许的方法是 a GET
,并且您不允许POST
在服务器端使用 :
Access-Control-Allow-Origin: *
This header only enables CORS, but you need to add this:
此标头仅启用 CORS,但您需要添加以下内容:
Access-Control-Allow-Methods: POST, GET
More detailed how-to about the HTTP access control (CORS)
on Mozilla project
HTTP access control (CORS)
关于 Mozilla 项目的更详细的操作方法
So your code should be something like this:
所以你的代码应该是这样的:
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
Update:
更新:
I have re-read the article, and found out some details:
我重读了这篇文章,发现了一些细节:
A simple cross-site request is one that:
- Only uses GET, HEAD or POST. If POST is used to send data to the server, the
Content-Type
of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.- Does not set custom headers with the HTTP Request (such as X-Modified, etc.)
一个简单的跨站点请求是:
- 仅使用 GET、HEAD 或 POST。如果使用 POST 向服务器发送数据,则
Content-Type
通过 HTTP POST 请求发送到服务器的数据是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 之一。- 不使用 HTTP 请求设置自定义标头(例如 X-Modified 等)
As you can read in bold, you must set other Content-Type
for your data (currently it is contentType: "application/json; charset=utf-8",
) or use the preflight technique described later:
正如您可以用粗体阅读的那样,您必须Content-Type
为您的数据设置 other (当前为contentType: "application/json; charset=utf-8",
)或使用稍后描述的预检技术:
- It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
- It sets custom headers in the request(e.g. the request uses a header such as X-PINGOTHER)
- 它使用 GET、HEAD 或 POST 以外的方法。此外,如果 POST 用于发送内容类型不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 的请求数据,例如,如果 POST 请求向服务器发送 XML 有效负载使用 application/xml 或 text/xml,然后预检请求。
- 它在请求中设置自定义标头(例如,请求使用 X-PINGOTHER 等标头)
So I suggest you either change the contentType or try to work with this header into your request:
因此,我建议您更改 contentType 或尝试将此标头处理到您的请求中:
Access-Control-Request-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE
and this headers into your response:
并将此标头包含在您的回复中:
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE
And after that you can try to call your method.
之后,您可以尝试调用您的方法。
回答by Sumit Sundriyal
Following is the solution for cross platform spring boot web service call.
以下是跨平台spring boot web服务调用的解决方案。
Application URL: http://localhost:8080
Webservice URL: http://localhost:9090
网络服务网址:http://localhost:9090
In your spring controller use following annotation
在您的弹簧控制器中使用以下注释
@CrossOrigin(origins = "http://localhost:8080")
@RequestMapping(value = "/uri", method = RequestMethod.GET)
public SomeObject someMethod(){
// your logic will come here
}