我已经使用 Jersey 实现了 REST 服务。为了提供更多的安全性,我在 REST 方法中添加了 jersey 安全注释(@PermitAll,@DenyAll)。
下面是我的示例 REST 服务:
@GET
@Path("/getall")
@Produces(MediaType.APPLICATION_JSON)
@PermitAll
public String getChartSupportedData(@QueryParam("items") int result) {
// my code goes here
}
Run Code Online (Sandbox Code Playgroud)
但问题是以前我使用javax.servlet.Filter过滤器来验证 URI。
网页.xml:
@GET
@Path("/getall")
@Produces(MediaType.APPLICATION_JSON)
@PermitAll
public String getChartSupportedData(@QueryParam("items") int result) {
// my code goes here
}
Run Code Online (Sandbox Code Playgroud)
根据访问一些 REST 服务,HttpServletRequest应该包含一个有效的令牌(由应用程序生成)。
某些 REST 端点不需要令牌来访问服务。在这种情况下,我必须在过滤器实现中绕过它:
private static String[] bypassPaths = { "/data/getall" };
Run Code Online (Sandbox Code Playgroud)
所以我的要求是这样的。
如果我们将某个 REST 端点声明@PermitAll为该路径,则不应在过滤器中将其声明为旁路路径,以便任何人都可以在没有有效令牌的情况下访问它。
但问题是当请求进入服务器时过滤器总是过滤,如果它不在旁路数组中,即使我声明为@PermitAll.
我想知道是否可以在同一个 Web 应用程序中组合这两个安全选项。
由于您正在执行身份验证和/或授权,因此我建议使用名称绑定过滤器而不是 servlet 过滤器,这样您就可以轻松地将它们绑定到您需要的资源。
要将过滤器绑定到您的 REST 端点,JAX-RS 提供了元注释@NameBinding,可以如下使用:
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured { }
Run Code Online (Sandbox Code Playgroud)
该@Secured注解将用于装饰过滤器类,它实现ContainerRequestFilter,允许您处理请求。
在ContainerRequestContext帮助你提取HTTP请求信息(更多详情,看看该ContainerRequestContextAPI):
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Use the ContainerRequestContext to extract information from the HTTP request
// Information such as the URI, headers and HTTP entity are available
}
}
Run Code Online (Sandbox Code Playgroud)
ContainerRequestFilter#filter()如果用户未经过身份验证/授权,则该方法是中止请求的好地方。为此,您可以使用ContainerRequestContext#abortWith()或抛出异常。
该@Provider注解标记了一个扩展接口的实现,在提供者扫描阶段应该可以被 JAX-RS 运行时发现。
要将过滤器绑定到您的端点方法或类,请使用@Secured上面创建的注释对它们进行 注释。对于注释的方法和/或类,将执行过滤器。
@Path("/")
public class MyEndpoint {
@GET
@Path("{id}")
@Produces("application/json")
public Response myUnsecuredMethod(@PathParam("id") Long id) {
// This method is not annotated with @Secured
// The security filter won't be executed before invoking this method
...
}
@DELETE
@Secured
@Path("{id}")
@Produces("application/json")
public Response mySecuredMethod(@PathParam("id") Long id) {
// This method is annotated with @Secured
// The security filter will be executed before invoking this method
...
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,安全过滤器将只被执行,mySecuredMethod(Long)因为它用@Secured.
您可以根据需要为 REST 端点设置任意数量的过滤器。为确保过滤器的执行顺序,请使用@Priority.
强烈建议使用Priorities类中定义的值之一(将使用以下顺序):
如果您的过滤器未使用 注释@Priority,则过滤器将USER优先执行。
您可以将此方法与Jersey 安全机制结合起来。
此外,您可以注入ResourceInfo您的ContainerRequestFilter:
@Context
private ResourceInfo resourceInfo;
Run Code Online (Sandbox Code Playgroud)
它可用于获取Method与Class请求的 URL 匹配的和:
Class<?> resourceClass = resourceInfo.getResourceClass();
Method resourceMethod = resourceInfo.getResourceMethod();
Run Code Online (Sandbox Code Playgroud)
并从中提取注释:
Annotation[] annotations = resourceClass.getDeclaredAnnotations();
PermitAll annotation = resourceMethod.getAnnotation(PermitAll.class);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4239 次 |
| 最近记录: |