远程托管时 Spring REST api 不起作用

Posted

技术标签:

【中文标题】远程托管时 Spring REST api 不起作用【英文标题】:Spring REST api not working while hosted remotely 【发布时间】:2015-11-08 15:47:30 【问题描述】:

我写了一个春季休息服务。当我在localhost 上运行它时,它运行良好

        $.ajax(
            url:"http://localhost:8080/api/v1.0/basicSignup",
            type:"POST",
            contentType:"application/json",

但是当我尝试并托管在某个远程服务器上时

        $.ajax(
            url:"http://X.X.X.X/api/v1.0/basicSignup",
            type:"POST",
            contentType:"application/json",

它抛出错误

在铬

XMLHttpRequest cannot load http://X.X.X.X/api/v1.0/basicSignup. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8084' is therefore not allowed access.

在控制台中我看到Method 选项卡中显示options

在 Mozilla 中也显示OPTIONS

Response Headersview source
Allow   GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length  0
Date    Sat, 15 Aug 2015 15:15:07 GMT
Server  Apache-Coyote/1.1
Request Headersview source
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Access-Control-Request-He...    content-type
Access-Control-Request-Me...    POST
Cache-Control   no-cache
Connection  keep-alive
DNT 1
Host    X.X.X.X
Origin  null
Pragma  no-cache
User-Agent  Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1

【问题讨论】:

docs.spring.io/spring/docs/current/spring-framework-reference/… 【参考方案1】:

正如@JB 的评论所说,您可能需要实现CORS。基本上,single origin policy 不允许来自一个域的 javascript,比如 http://localhost:8084 对另一个域进行 AJAX 调用,比如默认情况下是 http://X.X.X.X。有一些机制可以处理这个问题,但人们似乎更喜欢 CORS,因为通常它看起来最方便和强大。

Spring Lemon 详细展示了如何使用 CORS。以下是我另一个项目的示例:

    在客户端代码中,我最初会设置这些 ajax 选项(或与每个调用一起)

    $.ajaxSetup(    // Initialize options for AJAX calls
    
        crossDomain: true,
    
        xhrFields: 
            withCredentials: true
        
        ...
    );
    

    在服务器端,有一个过滤器来设置 CORS 标头。 Spring 的最新版本(将与 Spring Boot 1.3 一起提供)有一个 easier way 用于在服务器端配置 CORS。但是,在一个使用 Spring Boot 1.2 的项目中,我会这样:

    @Component
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class SimpleCorsFilter implements Filter 
    
        @Value("$applicationUrl:http://localhost:8084")
        String applicationUrl;
    
        public void doFilter(ServletRequest req,
                ServletResponse res,
                FilterChain chain)
        throws IOException, ServletException 
    
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin",
                applicationUrl); // "*" does not work when withCredentials = true;
            response.setHeader("Access-Control-Allow-Methods",
                "GET, POST, PUT, PATCH, DELETE, OPTIONS");
            response.setHeader("Access-Control-Max-Age",
                "3600");
            response.setHeader("Access-Control-Allow-Headers",
                "x-requested-with,origin,content-type,accept,X-XSRF-TOKEN");
            response.setHeader("Access-Control-Allow-Credentials", "true"); // needed when withCredentials = true;
    
            HttpServletRequest request =  (HttpServletRequest) req;
    
            if (!request.getMethod().equals("OPTIONS"))
               chain.doFilter(req, res);
        
    
        public void init(FilterConfig filterConfig) 
    
        public void destroy() 
    
    

    application.properties中设置applicationUrl,像这样

    applicationUrl: http://X.X.X.X
    

【讨论】:

如何从文件中调用服务器端服务,比如说file:///home/manish/test.html,这里它只是一个存储在目录中的 html 文件。那么这里上面的方法也可以吗? 浏览器甚至不允许您从文件系统提供的页面执行 AJAX 请求。 我在我的手机上运行我的 android aap 所以在这种情况下如何处理来自手机的请求,因为那不是localhost:// 在进行跨域请求之前,浏览器会询问服务器是否允许浏览器这样做。如果服务器拒绝,浏览器 会阻止它。如果您不从浏览器发送请求,那么没有什么可以阻止您执行跨源请求。顺便说一句,它不是跨域的,因为 android 应用程序不是网页,因此没有来源。

以上是关于远程托管时 Spring REST api 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Data MongoDB 的 Rest API - 存储库方法不起作用

使用Spring Data MongoDB的Rest API - 存储库方法不起作用

请求 REST POST API 在 Postman 中工作,但在 Alamofire 中不起作用

如何使用 Spring 在单元测试中模拟远程 REST API?

在 Spring Boot 应用程序中从 Angular JS 调用 Rest Services 时出错

托管基于 Java 的 REST API 服务