如何在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.Filter
filter来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匹配的Method
和Class
:
Class> resourceClass = resourceInfo.getResourceClass(); Method resourceMethod = resourceInfo.getResourceMethod();
并从中提取注释:
Annotation[] annotations = resourceClass.getDeclaredAnnotations(); PermitAll annotation = resourceMethod.getAnnotation(PermitAll.class);