【问题标题】:AngularJS -> Java: POST/PUT request results in 'Preflight request doesn't pass access control check'AngularJS-> Java:POST/PUT 请求导致“预检请求未通过访问控制检查”
【发布时间】:2018-07-04 06:12:54
【问题描述】:

通过搜索问题,我发现这与 CORS 有关。我不确定解决它的最佳方法是什么。

我正在运行一个具有各种 GET/POST/PUT/DELETE 资源的 Java Web 服务。它是一个使用 jersey/jax-rs 的 dropwizard 应用程序。我决定使用 AngularJS 为它构建一个 GUI 应用程序。我可以很好地发出 GET 请求,但是当我尝试发出 POST 或 PUT 请求时,我收到此错误:

对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

制作 PUT 的角码部分如下所示:

$http.put(url, data).
then(function(response) {
    $scope.message = response.data;

它正在与快递一起送达:

var express = require('express'),
    app = express(),
    bodyParser = require('body-parser'),
    morgan = require('morgan'),
    path = require('path');

app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());

app.use(function(req, res, next) {   res.setHeader('Access-Control-Allow-Origin', '*');   res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');   res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type, Authorization, Accept');   next(); });

app.use(express.static(__dirname + '/app'));

app.get('*', function(req, res) {   res.sendFile(path.join(__dirname + '/index.html')); });

app.listen(8080); console.log("running on 8080");

如前所述,Java 服务有不同的资源,例如:

@PUT
@Path("/insert/{operation}/{id}")
@Produces(MediaType.TEXT_PLAIN)
public Response addEntry ...

作为回复的一部分,我添加了一些其他帖子/问题建议的标题:

public static Response success(String content) {
    CustomResponse skeletonRsponse = response(content);
    return Response.status(Status.OK).entity(skeletonRsponse.getContent())
        .header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
        .build();
}

但错误仍然存​​在。 我通过查看服务器日志注意到来自 Angular 应用程序的请求被发送为

[25/Jan/2018:00:11:49 +0000]“选项...”

而不是“PUT...”

根据我对 CORS 的理解以及 angular $http 的工作原理(有限),会发送一个“OPTIONS”请求,如果一切正常,则发送实际请求。那么我该怎么办呢?我的一个想法是制作返回正确标题的@Options 资源,但这似乎不是最佳选择,因为我必须为每个现有资源创建一个以弥补正确的路径。

非常感谢任何帮助!

【问题讨论】:

    标签: java angularjs express dropwizard


    【解决方案1】:

    HTTP OPTIONS 方法用于描述目标资源的通信选项。参考link

    OPTIONS 请求不需要实现。只需尝试在响应中的 “Access-Control-Allow-Methods” 的标头值中添加 OPTIONS

    【讨论】:

    • 在构造Response的时候添加到Java Service中?
    • 是的,您在其中添加了其他 HTTP 方法 - GET、POST、PUT 和 DELETE
    • 好的,我会试试的。我唯一担心的是,由于它以“OPTIONS”的形式出现,因此没有任何资源会识别它,因为它们被 POST、PUT 等注释,但没有 OPTIONS。
    • 如有疑问,请参阅我的更新答案。另外,让我知道它是否解决了您的问题。如果是,也请采纳。
    【解决方案2】:

    使用org.eclipse.jetty.servlets.CrossOriginFilter。这是 Kotlin 代码,但我认为您可以将其整理出来:

    override fun run(configuration: BackendConfig, environment: Environment) {
        // ...
        addServletFilter(CrossOriginFilter::class.java, environment).apply {
            setInitParameter("allowedOrigins", "*")
            setInitParameter("allowedHeaders", "Content-Type,Accept,Origin," + CsrfProtectionFilter.HEADER_NAME)
            setInitParameter("allowedMethods", "OPTIONS,GET,PUT,POST,DELETE,HEAD")
        }
    }
    
    private fun addServletFilter(filterClass: Class<out Filter>, environment: Environment): FilterRegistration.Dynamic {
        val filter = environment.servlets().addFilter(filterClass.simpleName, filterClass)
        filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType::class.java), true, environment.jersey().urlPattern)
        return filter
    }
    

    PS。我实际上即将创建一个“过滤器”包,它在 DropWizard 中配置有用的过滤器并具有合理的默认值,但它还没有准备好!

    【讨论】:

      猜你喜欢
      • 2022-01-04
      • 2019-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-25
      • 2017-04-04
      • 2018-04-14
      • 2016-06-05
      相关资源
      最近更新 更多