从过滤器访问servlet注释

时间:2017-03-16 21:47:31

标签: java servlets java-ee

我需要一个在每个servlet之前调用的过滤器,并检查该servlet是否有一个注释,指出它需要身份验证,例如Servlet 3中的@ServletSecurity(@HttpConstraint(rolesAllowed={"user"}))。如果不是这样,那么过滤器将只是返回。如果servlet需要身份验证,它将检查请求令牌是否具有user角色,如果它没有自动设置NOT_AUTHENTICATED响应,甚至不通过servlet。< / p>

此作业必须由过滤器完成,因为我需要从请求中验证JWT令牌并将decodeJWT添加到请求中,以便servlet可以使用它的有效负载。

如何从过滤器检查servlet注释?在这种情况下,我可以在servlet中创建一个更简单的注释,如@RequiresAuth吗?因为我不需要在这个项目中担任角色。

是否可以在不通过servlet的情况下从过滤器返回未经过身份验证的客户端响应?

是否可以通过编程方式将过滤器设置为第一个?

这就是我使用Jersey解决它的方法,但我需要一个只有servlet的解决方案:

@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext context) {
        final Method method = resourceInfo.getResourceMethod();

        if (method.isAnnotationPresent(PermitAll.class)) return;
        if (method.isAnnotationPresent(DenyAll.class)) {
            context.abortWith(Response.status(Response.Status.FORBIDDEN).build());
            return;
        }

        final RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
        if (rolesAnnotation == null) return;
    }
}

1 个答案:

答案 0 :(得分:0)

<块引用>

如何检查过滤器中的 servlet 注释?在这种情况下,我可以在 servlet 中创建一个像 @RequiresAuth 这样更简单的注释吗?因为我不需要这个项目中的角色。

这是可能的,但不建议这样做。过滤器旨在有选择地应用于需要它们的 servlet。在您的情况下,我只会将其映射到那些需要身份验证的 servlet。

在您的 Jersey 示例中,AuthenticationFilter 适用于所有端点。使用 servlet 过滤器,您可以决定要将此过滤器应用于哪些 servlet/url-patterns。在这里对注释进行内省不再有意义。

<块引用>

是否可以不通过 servlet 就从过滤器向客户端返回一个未经身份验证的响应?

是的。您通过调用 response.setStatus(401) 而不是 chain.doFilter 从过滤器返回。

if (isAuthenticated()) {
    // this proceeds to the next filter or servlet in the chain
    chain.doFilter(request, response);
}
else {
    // this returns the response to the client
    response.setStatus(401);
}
<块引用>

是否可以以编程方式将过滤器设置为第一个过滤器?

是的。通过注解是不可能的,但是通过 web.xml 是可能的。这只是任何给定 servlet 或 url-pattern 的元素顺序。

<filter>
    <filter-name>filter1</filter-name>
    <filter-class>filter.Filter1</filter-class>
</filter>

<filter>
    <filter-name>filter2</filter-name>
    <filter-class>filter.Filter2</filter-class>
</filter>
    
<!-- filter2 will be applied 1st because it's listed 1st -->
<filter-mapping>
    <filter-name>filter2</filter-name>
    <servlet-name>some-servlet</servlet-name>
</filter-mapping>

<!-- filter1 will be applied after filter2 -->
<filter-mapping>
    <filter-name>filter1</filter-name>
    <servlet-name>some-servlet</servlet-name>
</filter-mapping>