如何在Java中使用Jersey安全注释绕过servletfilter中的路径

我使用Jersey实现了REST服务。 为了提高安全性,我在REST方法中添加了泽西安全注释( @PermitAll@DenyAll )。

以下是我的示例REST服务:

 @GET @Path("/getall") @Produces(MediaType.APPLICATION_JSON) @PermitAll public String getChartSupportedData(@QueryParam("items") int result) { // my code goes here } 

但问题是以前我使用javax.servlet.Filterfilter来validationURI。

web.xml中:

  ApplicationFilter web.filter.ApplicationFilter   ApplicationFilter /rest/api/* REQUEST ASYNC  

根据访问一些REST服务, HttpServletRequest应该包含一个有效的令牌(由应用程序生成)。

某些REST端点不需要令牌来访问服务。 在这种情况下,我必须在filter实现中绕过它:

 private static String[] bypassPaths = { "/data/getall" }; 

所以我的要求是这样的。

如果我们将一些REST端点声明为@PermitAll@PermitAll该路径不应该在filter中声明为旁路路径,这样任何人都可以在没有有效令牌的情况下访问它。

但问题是,当请求进入服务器时,filter总是过滤,如果它不在旁路arrays中,则请求不会继续,即使我声明为@PermitAll

我想知道是否可以在同一个Web应用程序中组合这两个安全选项。

由于您正在执行身份validation和/或授权,我建议使用名称绑定filter而不是servletfilter,因此您可以轻松地将它们绑定到您需要的资源。

要将filter绑定到REST端点,JAX-RS提供了元注释@NameBinding ,可以按如下方式使用:

 @NameBinding @Retention(RUNTIME) @Target({TYPE, METHOD}) public @interface Secured { } 

@Secured注释将用于修饰filter类,该类实现ContainerRequestFilter ,允许您处理请求。

ContainerRequestContext可帮助您从HTTP请求中提取信息(有关更多详细信息,请查看ContainerRequestContext API ):

 @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 } } 

如果用户未经过身份validation/授权,则ContainerRequestFilter#filter()方法是中止请求的好地方。 为此,您可以使用ContainerRequestContext#abortWith()或抛出exception。

@Provider注释标记了在提供程序扫描阶段JAX-RS运行时应该可以发现的扩展接口的实现。

要将filter绑定到端点方法或类,请使用上面创建的@Secured注释对其进行注释。 对于注释的方法和/或类,将执行filter。

 @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 ... } } 

在上面的示例中,安全filter将仅针对mySecuredMethod(Long)执行,因为它使用@Secured注释。

您可以根据需要为REST端点提供尽可能多的filter。 要确保filter的执行顺序,请使用@Priority注释它们。

强烈建议使用Priorities类中定义的值之一(将使用以下顺序):

  • AUTHENTICATION
  • AUTHORIZATION
  • ENTITY_CODER
  • HEADER_DECORATOR
  • USER

如果您的filter未使用@Priority注释, @Priority使用USER优先级执行filter。

您可以将此方法与Jersey安全机制结合使用。

此外,您可以在ContainerRequestFilter注入ResourceInfo

  @Context private ResourceInfo resourceInfo; 

它可用于获取与请求的URL匹配的MethodClass

  Class resourceClass = resourceInfo.getResourceClass(); Method resourceMethod = resourceInfo.getResourceMethod(); 

并从中提取注释:

  Annotation[] annotations = resourceClass.getDeclaredAnnotations(); PermitAll annotation = resourceMethod.getAnnotation(PermitAll.class);