- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 REST API,我希望其中的一些 方法具有特定的 CORS header 。我在资源方法上有一个注解,还有一个过滤器来添加标题:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface CorsHeaders {}
@Path("api")
class MyApi {
@CorsHeaders
@GET
public Response m() {
return Response.ok().build();
}
}
@Provider
class CorsFilter implements ContainerResponseFilter {
@Context private ResourceInfo resourceInfo;
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
if (resourceInfo.getResourceMethod().getAnnotation(CorsHeaders.class) != null) {
responseContext.getHeaders().add(/* appropriate headers here*/);
}
}
}
这适用于所有 GET、POST 等请求。它不适用于 OPTIONS 请求,因为资源方法将解析为 org.glassfish.jersey.server.wadl.processor.WadlModelProcessor$OptionsHandler
而不是我的方法,因此注释将不存在.
我可以通过添加一个 @OPTIONS @CorsHeaders public Response options() { return Response.ok().build(); 来解决这个问题}
方法添加到我的 API 类(在相同的 @Path
上),但我不想对所有方法都这样做。
在处理 OPTIONS 请求时如何找到实际的 (GET/POST) 资源方法?
最佳答案
恐怕在不更改 Jersey 本身的情况下使用当前版本实际上不可能以一种很好的方式实现您想要完成的目标。
无论如何,根据规范规范,我也不太确定使用 @Provider
请求特定过滤器是否是正确的方法。但我是谁说的 我实际上是自己做的。当然也可以在 ResourceConfig
中注册过滤器。一般来说,我建议看一下 @NameBinding
,但对于这种情况,名称绑定(bind) Jersey-style 是不够的。使用 @NameBinding
,您不必自己检查注释,因为 Jersey 已经为您完成了。
不幸的是再次使用 @NameBinding
,它是为这种情况引入的,存在“自动生成”选项处理程序的问题。我做了很多挖掘(一些最相关的类/方法是 OptionsMethodProcessor
、WadlModelProcessor
、ResourceModelConfigurator#init
和 ServerRuntime ApplicationHandler# initialize
) 但没有找到一种方法来充分 Hook 到进程中。以下是足以处理 CORS 的内容:
@NameBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CrossOrigin {
}
@CrossOrigin
public class CrossOriginResponseFilter implements ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext)
throws IOException {
// do Cross Origin stuff
}
}
@Path("ress")
public class MyResource {
@CrossOrigin
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response save(DetailsDTO details) {
// do something with the details
}
}
但是,虽然这适用于对资源的任何直接请求,但这也不适用于 CORS-preflight-requests,因为 Jersey 不将名称绑定(bind)注释 @CrossOrigin
应用于预定义/自动生成的选项处理程序。您可以看到,在请求上下文中查看资源的运行时表示时(不要让所有文本激怒您,重要的是每个 nameBindings
末尾的属性 资源方法
):
[ResourceMethod{
httpMethod=POST, consumedTypes=[application/json],
producedTypes=[application/json], suspended=false, suspendTimeout=0,
suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class de.example.MyResource,
handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@2c253414]}, definitionMethod=public javax.ws.rs.core.Response de.example.MyResource.save(de.example.DetailsDTO),
parameters=[Parameter [type=class de.example.DetailsDTO, source=null, defaultValue=null]],
responseType=class javax.ws.rs.core.Response},
nameBindings=[interface de.example.CrossOrigin]},
ResourceMethod{
httpMethod=OPTIONS, consumedTypes=[*/*],
producedTypes=[application/vnd.sun.wadl+xml], suspended=false,
suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS,
invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.WadlModelProcessor$OptionsHandler,
handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@949030f]},
definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object),
parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]], responseType=class javax.ws.rs.core.Response},
nameBindings=[]},
ResourceMethod{
httpMethod=OPTIONS, consumedTypes=[*/*], producedTypes=[text/plain],
suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS,
invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$PlainTextOptionsInflector,
handlerConstructors=[]}, definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object),
parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]],
responseType=class javax.ws.rs.core.Response}, nameBindings=[]},
ResourceMethod{
httpMethod=OPTIONS, consumedTypes=[*/*], producedTypes=[*/*],
suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS,
invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor$GenericOptionsInflector,
handlerConstructors=[]}, definitionMethod=public abstract java.lang.Object org.glassfish.jersey.process.Inflector.apply(java.lang.Object),
parameters=[Parameter [type=interface javax.ws.rs.container.ContainerRequestContext, source=null, defaultValue=null]], responseType=class javax.ws.rs.core.Response},
nameBindings=[]}]
但是现在您可以通过创建另一个过滤器使用名称绑定(bind)信息来自己处理预检请求:
@Provider
@Priority(1)
public class CrossOriginResponseFilter implements ContainerRequestFilter {
Resource res = ((ContainerRequest)requestContext)
.getUriInfo().getMatchedResourceMethod().getParent();
if (res.getResourceMethods().get(0).getNameBindings().contains(CrossOrigin.class)) {
// handlePreflightRequest and abort: requestContext.abortWith(builder.build());
}
}
有趣的是,提取的资源 res
将仅包含与实际请求 URI 和方法匹配的相关资源方法以及自动生成的 OPTIONS-handlers,如您在上面的运行中所见-资源方法的时间表示。示例资源实际上有更多方法、POST 和 GET。因此,您可以在此处使用 .get(0)
访问所需的信息。
但请注意! 我没有检查这是否在任何情况下都是正确的,或者只是当您例如用单独的路径注释您的资源方法时。因此,与我这里的简单版本相比,可能需要做更多的匹配工作。
我自己发现该解决方案非常丑陋,最终得到的过滤器不是特定于方法的,而是简单地处理对任何资源的所有请求(类似于 here 的解决方案)。但它应该是对如何“在处理 OPTIONS 请求时找出实际的 (GET/POST) 资源方法”这个问题的答案。
关于java - 带有 Jersey 的 OPTIONS 请求的 CORS header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38009678/
我尝试访问此 API click here for more info POST https://api.line.me/v2/oauth/accessToken 但总是得到错误: XMLHttpRe
我在掌握 CORS 概念时遇到问题... 我认为同源策略保护应用程序不会对“不受信任的域”进行 ajax 调用。所以, mydomain.com 向 发出 ajax 调用somedomain.com
一个技术性很强的问题,可能只有了解浏览器内部结构的人才能回答...... 浏览器缓存 CORS 预检响应的准确程度如何(假设在对 OPTIONS 预检请求的响应中返回了 Access-Control-
我一直在阅读 CORS以及它是如何工作的,但我发现很多事情令人困惑。例如,有很多关于事情的细节,比如 User Joe is using browser BrowserX to get data fr
在 OWASP site 上看到这个矛盾,我感到很困惑。 CORS 备忘单: 使用 Access-Control-Allow-Credentials: true 响应 header 时要特别小心。将允
我们无法在飞行前恢复使用 cors:任何帮助都非常感谢 ==========错误========================== About to connect() to localhost p
跨域请求字体文件时,您必须确保允许请求域使用 CORS header 访问字体文件: 访问控制允许来源 访问控制允许凭据 然而,这在请求图像时不是必需的,无论是对于 img元素或 background
CORS 规范没有说明服务器应如何响应无效的 CORS 请求。例如,如果请求 Origin 无效,则 CORS spec states :“终止这组步骤。请求超出了本规范的范围。”其他错误情况也有类似
我在理解同源策略和“解决”它的不同方法时遇到了一些麻烦。 很明显,同源策略是作为一种安全措施而存在的,因此来自服务器/域的一个脚本无法访问来自另一个服务器/域的数据。 也很明显,有时能够打破此规则很有
我正在尝试使用 cloudformation 在 API Gateway 中部署 API。这些方法需要启用 CORS,我遵循此处的模板 Enable CORS for API Gateway in C
我正在构建一个使用 CORS 的 REST 应用程序。每个 REST 调用都是不同的,我发现获取预检 OPTIONS 调用会产生很大的开销。有没有办法缓存并应用预检选项结果,以便对同一域的任何后续调用
我正在将我的 WebApi 升级到 MVC6。 在 WebApi 中,我可以拦截每个 HTTP 请求,如果是预检,我可以用浏览器可以接受的 header 进行响应。 我正在尝试找出如何在 MVC6 W
假设一个 CORS 预检请求进来了,但它为一个或多个 Access-Control-Request-* 指定了一个不受支持的值。标题。服务器应该如何将其传达回浏览器? 一些例子: 浏览器发送带有 Ac
问题中的一切。 附加信息: 使用 Win 10,GraphDB 免费,9.1.1 • RDF4J 3.0.1 • Connectors 12.0.2 我在控制台 => 设置中添加了 graphdb.w
我正在尝试通过 jQuery 调用 Sonar 网络服务之一。由于调用是跨域进行的,因此调用在 Chrome 上失败并出现以下错误: 请求的资源上不存在“Access-Control-Allow-Or
我想使用 NestJs api,但我在每个 fetch 中都收到相同的错误消息: Access to fetch at 'http://localhost:3000/articles' from or
我不确定这是否属于这里,但我在开发我的 svelte 应用程序时遇到了问题。 在开发过程中,它目前在独立服务器上运行(遵循使用 rollup 和 sirv 的指南)并针对不同端口上的后端 API。 稍
如果在服务器上正确设置 CORS 以仅允许某些来源访问服务器,这是否足以防止 XSRF 攻击? 最佳答案 更具体地说,很容易错误地认为如果 evil.com 由于 CORS 无法向 good.com
我在 Istio 入口上启用 CORS 时遇到问题。正如 Istio Ingress 文档所述,“ingresskubernetes.io”注释将被忽略。是否可以在 Istio 入口上启用 CORS?
我在 Istio 入口上启用 CORS 时遇到问题。正如 Istio Ingress 文档所述,“ingresskubernetes.io”注释将被忽略。是否可以在 Istio 入口上启用 CORS?
我是一名优秀的程序员,十分优秀!