无法调用spring REST服务
我的春季服务
@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);
}
我的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
我如何摆脱这个错误,任何帮助?
答案 0 :(得分:8)
我的AJAX通话和服务都没问题。在互联网上搜索了很多后,我发现它的服务器端问题不是客户端。
在服务器端使用Spring,我们必须实现允许CORS请求的过滤器。过滤器看起来像这样。
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>
<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>
这可能有助于遇到此问题的其他人。 :)
答案 1 :(得分:2)
默认情况下,唯一允许的方法是GET
,并且您不允许服务器端的POST
:
Access-Control-Allow-Origin: *
此标头仅启用CORS,但您需要添加以下内容:
Access-Control-Allow-Methods: POST, GET
关于Mozilla项目的 More detailed how-to about the 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将数据发送到 server,使用HTTP发送到服务器的数据的
Content-Type
POST请求是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 使用除以外的Content-Type发送请求数据 application / x-www-form-urlencoded,multipart / form-data或text / plain, 例如如果POST请求使用XML向服务器发送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
然后你可以尝试调用你的方法。
答案 2 :(得分:0)
以下是跨平台spring boot Web服务调用的解决方案。
应用程序网址:http://localhost:8080
网络服务网址:http://localhost:9090
在弹簧控制器中使用以下注释
@CrossOrigin(origins = "http://localhost:8080")
@RequestMapping(value = "/uri", method = RequestMethod.GET)
public SomeObject someMethod(){
// your logic will come here
}