AngularJS->;Java:POST/PUT请求结果为';飞行前请求不';t通过访问控制检查';

AngularJS->;Java:POST/PUT请求结果为';飞行前请求不';t通过访问控制检查';,java,angularjs,express,dropwizard,Java,Angularjs,Express,Dropwizard,通过四处寻找这个问题,我发现这与CORS有关。我不知道最好的解决办法是什么 我有一个运行的JavaWeb服务,它有各种GET/POST/PUT/DELETE资源。这是一个dropwizard应用程序,使用jersey/jax-rs。我决定使用AngularJS为它构建一个GUI应用程序。我可以发出GET请求,但当我尝试发出POST或PUT请求时,会出现以下错误: 对飞行前请求的响应未通过访问控制检查:否 “Access Control Allow Origin”标头出现在请求的服务器上 资源 构

通过四处寻找这个问题,我发现这与CORS有关。我不知道最好的解决办法是什么

我有一个运行的JavaWeb服务,它有各种GET/POST/PUT/DELETE资源。这是一个dropwizard应用程序,使用jersey/jax-rs。我决定使用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应用程序的请求被发送为

[2018年1月25日:00:11:49+0000]“选项…”

而不是“放…”

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


非常感谢您的帮助

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


选项
请求不需要实现。只需在响应中的
“Access Control Allow Methods”
的标题值中添加
选项即可。

使用
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
}
override fun run(配置:BackendConfig,环境:environment){
// ...
addServletFilter(CrossOriginFilter::class.java,环境)。应用{
setInitParameter(“AllowedOriginates”,“*”)
setInitParameter(“allowedHeaders”、“内容类型、接受、来源”+CsrfProtectionFilter.HEADER\u名称)
setInitParameter(“allowedMethods”、“OPTIONS、GET、PUT、POST、DELETE、HEAD”)
}
}
private fun addServletFilter(filterClass:Class,environment:environment):FilterRegistration.Dynamic{
val filter=environment.servlets().addFilter(filterClass.simpleName,filterClass)
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType::class.java),true,environment.jersey().urlPattern)
回流过滤器
}

另外,我实际上要创建一个“过滤器”包,在DropWizard中用合理的默认值配置有用的过滤器,但它还没有准备好

在构建响应时将其添加到Java服务中?是的,您在其中添加了其他HTTP方法-GET、POST、PUT和DELETEOK。我将尝试这样做。我唯一担心的是,由于它是以“选项”的形式出现的,因此没有任何资源会识别它,因为它们是用POST、PUT等注释的,而不是选项。请查看我的更新答案以了解您的疑问。另外,如果它解决了你的问题,请告诉我。如果是,请同时接受答案。