【问题标题】:No 'Access-Control-Allow-Origin' header is present on the requested resource - Resteasy请求的资源上没有“Access-Control-Allow-Origin”标头 - Resteasy
【发布时间】:2016-01-14 20:37:27
【问题描述】:

我正在开发一个包含 UI-Angular、Server-Java、RestEasy 3.0.9.Final 的 web 应用程序,用于 rest api 调用

当我尝试从另一个域访问其余服务时出现以下错误

无法加载对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'http://localhost:8080'。

我将服务器端配置为响应跨域调用,这与 GET 调用一起使用,但 POST 调用正在创建错误

web.xml

<context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>com.test.sample.app.CorsFeature</param-value>
</context-param>

<listener>
    <listener-class>
        org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.test.sample.app.Application</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
</context-param>
<context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
</context-param>

服务类

@GET
@Path("/getnameAtt")
@Produces(MediaType.APPLICATION_JSON)
public Response getHostnameAttributes() {
return Response
.status(200)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers",
        "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods",
        "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.entity(new TestImpl().getHostNameAttributes())
.build();
}

@POST
@Path("/getSeq")
@Produces(MediaType.APPLICATION_JSON)
public Response getCurrentSequence(String request) {
return Response
.status(200)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers",
        "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods",
        "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.entity(new TestImpl().getCurrentSeq(request))
.build();
}

由于我是 resteasy 的新手,无法弄清楚为什么这不起作用。 任何帮助将不胜感激 。等待您的回复。

谢谢

【问题讨论】:

    标签: rest cors resteasy


    【解决方案1】:

    您的资源方法不会受到影响,因此它们的标头永远不会被设置。原因是在实际请求之前存在所谓的预检请求,即OPTIONS 请求。所以错误来自预检请求没有产生必要的标头。

    对于 RESTeasy,您应该使用 CorsFilter。您可以查看here 以了解如何配置它的一些示例。此过滤器将处理预检请求。因此,您可以删除资源方法中的所有标头。

    另请参阅:

    【讨论】:

    • 感谢您的回复。已使用该 CorsFilter 并使用 @Provider 进行注释。但是那个类甚至没有被调用。我需要在 web.xml 中添加任何内容吗
    • 我链接到的那个例子是为了如果你正在扫描资源。如果您明确注册了所有资源和提供程序,那么您只需在您的 Application 类中注册 CorsFilter。或注册Feature。无论哪种方式都有效。但不需要Feature。您可以在Application 类中覆盖getSingletons() 时注册CorsFilter
    • 预检请求应该是明确的还是由浏览器内部处理?在发送实际请求之前,我是否必须先发送 OPTION 预检请求?我遇到了类似的错误。
    • @SudipBhandari 不,对于任何需要跨源检查的请求,浏览器都会透明地处理整个交互。您只需要设置服务器来处理 OPTIONS 预检(通过发送适当的 CORS 响应标头)。这篇文章中提到的CorsFilter 就是这样做的。
    • @peeskillet 因此,如果我正在向 API 发布 POST,那么该 API 也应该处理预检选项吗?我问这个是因为当通过邮递员等客户完成时,响应是可以的。我的帖子请求中有自定义标头,但它仍然无法通过访问控制检查。此外,chrome 控制台中的错误消息是“没有 Access-Control-Allow-Origin 存在”,尽管它显然是这样,否则像“邮递员”这样的东西将如何成功接收响应。帮帮我
    【解决方案2】:

    您的资源POSTmethod 似乎不会像@peeskillet 提到的那样受到打击。很可能您的 ~POST~ 请求不起作用,因为它可能不是一个简单的请求。唯一简单的请求是 GET、HEAD 或 POST,并且请求标头很简单(唯一简单的标头是 Accept、Accept-Language、Content-Language、Content-Type= application/x-www-form-urlencoded、multipart/form-data , 文本/纯文本)。

    由于您已经将Access-Control-Allow-Origin 标头添加到您的响应中,您可以将新的OPTIONS 方法添加到您的资源类中。

        @OPTIONS
    @Path("{path : .*}")
    public Response options() {
        return Response.ok("")
                .header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
                .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
                .header("Access-Control-Max-Age", "2000")
                .build();
    }
    

    【讨论】:

      【解决方案3】:

      在遇到类似问题后,以下是我所做的:

      • 创建了一个扩展 javax.ws.rs.core.Application 的类并向其添加了 Cors 过滤器。

      在 CORS 过滤器中,我添加了 corsFilter.getAllowedOrigins().add("http://localhost:4200");

      基本上,您应该添加要允许跨域资源共享的 URL。 Ans 你也可以使用"*" 而不是任何特定的 URL 来允许任何 URL。

      public class RestApplication
          extends Application
      {
          private Set<Object> singletons = new HashSet<Object>();
      
          public MessageApplication()
          {
              singletons.add(new CalculatorService()); //CalculatorService is your specific service you want to add/use.
              CorsFilter corsFilter = new CorsFilter();
              // To allow all origins for CORS add following, otherwise add only specific urls.
              // corsFilter.getAllowedOrigins().add("*");
              System.out.println("To only allow restrcited urls ");
              corsFilter.getAllowedOrigins().add("http://localhost:4200");
              singletons = new LinkedHashSet<Object>();
              singletons.add(corsFilter);
          }
      
          @Override
          public Set<Object> getSingletons()
          {
              return singletons;
          }
      }
      
      • 这是我的 web.xml:
      <web-app id="WebApp_ID" version="2.4"
          xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
          <display-name>Restful Web Application</display-name>
      
          <!-- Auto scan rest service -->
          <context-param>
              <param-name>resteasy.scan</param-name>
              <param-value>true</param-value>
          </context-param>
      
          <context-param>
              <param-name>resteasy.servlet.mapping.prefix</param-name>
              <param-value>/rest</param-value>
          </context-param>
      
          <listener>
              <listener-class>
                  org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
              </listener-class>
          </listener>
      
          <servlet>
              <servlet-name>resteasy-servlet</servlet-name>
              <servlet-class>
                  org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
              </servlet-class>
              <init-param>
                  <param-name>javax.ws.rs.Application</param-name>
                  <param-value>com.app.RestApplication</param-value>
              </init-param>
          </servlet>
      
          <servlet-mapping>
              <servlet-name>resteasy-servlet</servlet-name>
              <url-pattern>/rest/*</url-pattern>
          </servlet-mapping>
      
      </web-app>
      

      最重要的代码当我遇到这个问题时,我没有添加我的扩展 javax.ws.rs.Application 的类,即 RestApplication 到 @987654325 的 init-param @

         <init-param>
              <param-name>javax.ws.rs.Application</param-name>
              <param-value>com.app.RestApplication</param-value>
          </init-param>
      

      因此我的过滤器无法执行,因此应用程序不允许来自指定 URL 的 CORS。

      【讨论】:

        猜你喜欢
        • 2017-02-07
        • 2023-03-16
        • 2014-07-30
        • 2023-03-15
        • 2018-12-02
        • 2015-10-30
        • 2019-10-07
        • 2021-09-28
        • 2021-02-23
        相关资源
        最近更新 更多