使用Dropwizard从Authenticator访问HttpServletRequest

Pie*_*ard 3 dependency-injection jersey dropwizard

使用DropWizard(Jersey服务器),是否可以HttpServletRequest从身份验证器访问?

我会给它一个属性.

我尝试过:

@Context
private HttpServletRequest servletRequest;
Run Code Online (Sandbox Code Playgroud)

但它没有注入.

我注册了我的身份验证器:

env.jersey().register(
                new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>().setAuthenticator(new FooAuthentificator())
                        .setRealm("Realm").buildAuthFilter()));
Run Code Online (Sandbox Code Playgroud)

Pau*_*tha 6

这是可能的,但问题是,Authenticator永远不会经历DI生命周期,所以它永远不会有机会被注入.我们可以做的就是自己明确注入它.要做到这一点,我们需要掌握ServiceLocator(这是主要的IoC容器,有点像ApplicationContextSpring).一旦我们拥有了ServiceLocator,我们可以调用locator.inject(anyObject)显式解决任何注入依赖项.

ServiceLocator在配置应用程序时,最容易获得的地方是Feature.在这里我们还可以注册Jersey组件.调用registerFeatureContext(如下所示),就像调用env.jersey().register(...)与Dropwizard,它具有相同的效果.所以我们可以做到

public class AuthenticatorFeature implements Feature {

    @Override
    public boolean configure(FeatureContext ctx) {
        ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(ctx);
        TestAuthenticator authenticator = new TestAuthenticator();
        locator.inject(authenticator);
        ctx.register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
                        .setAuthenticator(authenticator)
                        .setRealm("SEC REALM")
                        .buildAuthFilter()));
        ctx.register(new AuthValueFactoryProvider.Binder<>(User.class));
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以看到通过调用显式注入身份验证器locator.inject(authenticator).然后我们通过Dropwizard注册此功能

env.jersey().register(new AuthenticatorFeature());
Run Code Online (Sandbox Code Playgroud)

经过测试,效果很好.


注意,如果您想知道如何注入HttpServletRequest,当没有当前请求时,这是因为注入了代理.同样的事情就像你将请求注入Jersey过滤器一样,同样的事情发生了; 注入代理,因为只有单例过滤器,但请求从请求变为请求,因此需要注入代理.

也可以看看: