DropWizard中的自定义授权问题

时间:2015-12-16 05:08:37

标签: authentication authorization dropwizard

我正在尝试在dropwizard中添加自定义授权但无法成功。

我通过将其绑定到authFactory

为dropwizard添加了自定义身份验证
Authenticator ssoAuthenticator = createSSOAuthenticator(configuration.getSsoGrantClientConfiguration());
environment.jersey().register(AuthFactory.binder(
                    new SSOTokenAuthFactory<SSOGrant>(
                                       ssoAuthenticator,
                                          SYSTEM_PREFIX,
                                         SSOGrant.class))
 );

并添加动态功能以进行授权

environment.jersey().register(PermissionDynamicFeature.class);

以下是创建的注释

@Documented
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
public @interface PermissionsAllowed {
    String[] value();
}

我正在检查方法上是否存在注释,然后注册过滤器

public class PermissionDynamicFeature implements DynamicFeature {
@Override
    public void configure(final ResourceInfo resourceInfo, final FeatureContext configuration) {

        final AnnotatedMethod am = new AnnotatedMethod(resourceInfo.getResourceMethod());
        final Annotation[][] parameterAnnotations = am.getParameterAnnotations();
            for (Annotation[] annotations : parameterAnnotations) {
                for (Annotation annotation : annotations) {
                    if (annotation instanceof PermissionsAllowed) {
                        configuration.register(new RolesAllowedRequestFilter(((PermissionsAllowed)annotation).value()));
                        return;
                    }
                }
            }
        }



    //@Priority(Priorities.USER) // authorization filter - should go after any authentication filters
    private static class RolesAllowedRequestFilter implements ContainerRequestFilter {

        private final boolean denyAll;
        private final String[] rolesAllowed;

        RolesAllowedRequestFilter() {
            this.denyAll = true;
            this.rolesAllowed = null;
        }

        RolesAllowedRequestFilter(final String[] rolesAllowed) {
            this.denyAll = false;
            this.rolesAllowed = (rolesAllowed != null) ? rolesAllowed : new String[] {};
        }

        @Override
        public void filter(final ContainerRequestContext requestContext) throws IOException {
            if (!denyAll) {
                if (rolesAllowed.length > 0 && !isAuthenticated(requestContext)) {
                    throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
                }

                for (final String role : rolesAllowed) {
                    if (requestContext.getSecurityContext().isUserInRole(role)) {
                        return;
                    }
                }
            }

            throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
        }

        private static boolean isAuthenticated(final ContainerRequestContext requestContext) {
            return requestContext.getSecurityContext().getUserPrincipal() != null;
        }
    }
}

我只是想根据与RolesAllowed过滤器相同的行来构建我的授权。

我面临的问题是在身份验证之前调用了Authorization过滤器。 我缺少什么,以便首先进行身份验证,稍后调用授权过滤器?

当我们注册RolesAllowedDynamicFeature

时会发生同样的情况
environment.jersey().register(RolesAllowedDynamicFeature.class);

甚至在身份验证发生之前就会调用RolesAllowedDynamicFeature。

1 个答案:

答案 0 :(得分:0)

所以基于你的答案,我写了一个测试,我相信我可以告诉你这里的问题是什么。

您用于提供身份验证令牌的Authfactory不是请求过滤器。根据泽西的文档,这是请求的执行顺序:

https://jersey.java.net/documentation/latest/filters-and-interceptors.html#d0e9976

问题如下:

在执行绑定之前,将始终执行所有请求过滤器。在请求时,球衣甚至不知道它是否需要将任何东西绑定到你的方法上。为什么要创建任何东西,过滤器可能会在请求执行之前拒绝该请求。

简而言之,使用@Auth注释您的资源方法只需在您的泽西环境中添加注入活页夹。您可以在此处阅读自定义注入:

https://jersey.java.net/documentation/latest/ioc.html

这显然是正常的,非常方便,但不是你想要的。 你想要的是在它通过任何过滤器之前拒绝一个请求。为此你必须写一个请求过滤器。用正确的优先级注释它,一切都应该正常工作。

您可以考虑将auth逻辑提取到公共类(您已经做过),然后使用RequestFilter和Authenticator注册相同的类,从而保留Auth提供程序,同时仍然基于Authentication进行请求筛选

JTextField

添加缓存,您不必担心两次调用相同的内容。

我相信dropwizard并不打算使用过滤器。看来他们的目的是将auth上下文注入资源方法并在那里进行身份验证等。不是我首选的解决方案,但它可以工作。

总结一下:

开箱即用的dropwizard不支持您想要做的事情。解决方案是将其解决方案扩展到请求过滤器。

希望有所帮助,

阿图尔