gpt4 book ai didi

java - 如何在单个应用程序中部署多个 RestEasyInterceptor?

转载 作者:太空宇宙 更新时间:2023-11-04 13:39:33 25 4
gpt4 key购买 nike

我正在 JBoss 7.1.1 上使用 RestEasy 部署一些 Web 服务。我有两个类沿着同一路径处理不同的资源请求。 UserAPI.java 处理 /books/books/{id} 等。 MaintenanceAPI.java 处理 /books/checkedout

UserAPI 需要先前登录,该登录由名为 AuthInterceptor 的 RestEasyInterceptor 进行验证。维护 API 不需要登录,但只能通过 localhost 作为 GET 访问;它由 LocalInterceptor 处理。

为了将它们分开,如果 declaring.getName().contains("Maintenance"),AuthInterceptor 的accept() 方法将返回 false - 因此它根本不应该处理 /books/checkedout。如果declaring.equals(MaintenanceAPI.class),LocalInterceptor的accept()方法返回true。

AuthInterceptor 在 web.xml 的“resteasy.providers”下声明。但 Eclipse 认为 XML 元素中只能有 1 个参数,因此 LocalInterceptor 有注释 @Provider 希望它能神奇地工作。

拒绝 XML 配置

这失败了:

<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.foo.AuthInterceptor</param-value>
<param-value>com.foo.LocalInterceptor</param-value>
</context-param>

我不确定正确的语法是什么,RestEasy 文档中没有任何帮助。这也失败了:

<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.foo.AuthInterceptor</param-value>
</context-param>
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.foo.LocalInterceptor</param-value>
</context-param>

但是,发生的情况是,从远程计算机到 /books/checkedout 的 URL 请求(应该因 NOT_AUTHORIZED 而失败)被路由到 UserAPI 的 /books/{id}/ 处理程序,该处理程序继续尝试处理它并返回一个非常大的异常!这是错误的,有几个原因:它不是正确的路径,不是正确的处理程序,不是正确的参数类型,而且它应该需要一个身份验证 token !显然,LocalInterceptor 并不是通过注释神奇地添加的,因此它没有机会接受请求。 AuthInterceptor 必须正确拒绝它,但是为什么会要求 UserAPI 来处理它,而且为什么会为 int {id} 分配字符串“checkedout”?

我还没有发布代码,因为我问我是否可以做我正在尝试的事情(例如“为什么我不能子类化 String” - 如果你理解这个问题,则不需要代码)以及为什么映射试图做错误的事情而不是失败。

也许就像让 web.xml 正确一样简单?

最佳答案

对于您的 XML 配置(通常是 web.xml),这就是您要查找的内容。

<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.foo.AuthInterceptor, com.foo.LocalInterceptor</param-value>
</context-param>

您应该提供完全限定的 @Provider 类名的逗号分隔列表。这将确保您的 LocalInterceptor 也启动并完成其工作。 see Table 2.1 of the Documentation

也就是说,我假设您在 MaintenanceAPIUserAPI 接口(interface)上的 @Path 注释都类似于 @Path("/books")。我认为这是你问题的根源。

/books/checkedout 与接口(interface)入口级别的 /books/{id} 没有太大区别,直到请求到达处理方法为止,因此,如果对 /books/checkedout 的请求首先进入您的 UserAPI(需要 /books/{id}),则字符串 "checkedout" 将被读取为整数 { id},因此你的异常很大......(我猜这是一个 NumberFormatException 位于 StackTrace 的根部)。

站在你的立场上,我将仅使用一个接口(interface)来处理所有请求@Path("/books"),并更改我的方法路径以使其不相互冲突。

@Path("/books")
@Produces(MediaType.APPLICATION_JSON)
public interface BooksAPI{

@GET
@Path("/{id}")
public Response getBookByID(@PathParam("id") String id);
// so the url here looks like --> /books/1234

@GET
@Path("/status/checkedout")
public Response getCheckedOut();
// and the url here looks like --> /books/status/checkedout
}

或者如果我决定保留这两个界面,我将使入口路径不同。本质上是这样的;

@Path("/maintenance")
@Produces(MediaType.APPLICATION_JSON)
public interface MaintenanceAPI{

@GET
@Path("/books/checkedout")
public Response getCheckedOut();
}
// so the url here looks like --> /maintenance/books/checkedout

.

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
public interface UserAPI{

@GET
@Path("/books/{id}")
public Response getBookByID(@PathParam("id") String id);
}
// and the url here looks like --> /users/books/1234



其他建议 - 过滤来自 localhostremote 的请求,我以前曾经使用过的一种非常强大的技术是访问/角色管理,如下所示;

创建一个注释界面,例如

@Documented
@Retention (RUNTIME)
@Target({TYPE, METHOD})
public @interface RolesAllowed {
String[] value();
}

然后你的拦截器的accept()方法可能如下所示;

LocalInterceptor.java

@Override
public boolean accept(Class declaring, Method method) {
if(method.isAnnotationPresent(RolesAllowed.class)){
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<String (Arrays.asList(rolesAnnotation.value()));
return rolesSet.contains("local");
}
return false;
}

AuthInterceptor.java

@Override
public boolean accept(Class declaring, Method method) {
if(method.isAnnotationPresent(RolesAllowed.class)){
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<String (Arrays.asList(rolesAnnotation.value()));
return rolesSet.contains("remote");
}
return false;
}

最后根据需要使用所需的角色注释您的接口(interface)方法。 (注意 - 我正在使用上面指出的第一种方法) 例如;

@Path("/books")
@Produces(MediaType.APPLICATION_JSON)
public interface BooksAPI{

@GET
@Path("/{id}")
@RolesAllowed({"remote"})
public Response getBookByID(@PathParam("id") String id);

@GET
@Path("/status/checkedout")
@RolesAllowed({"local"})
public Response getCheckedOut();
}

关于java - 如何在单个应用程序中部署多个 RestEasyInterceptor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31358711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com