且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用Dropwizard从身份验证器访问HttpServletRequest

更新时间:2023-12-04 21:28:16

这是可能的,但问题是Authenticator从未经历过DI生命周期,因此它永远都没有机会被注入.我们可以做的是自己明确地注入它.为此,我们需要持有ServiceLocator(这是主要的IoC容器,有点像Spring的ApplicationContext).有了ServiceLocator后,我们可以调用locator.inject(anyObject)显式解决所有注入依赖项.

It's possible, but the problem is, the Authenticator never goes through the DI lifecycle, so it never gets a chance to get injected. What we can do though is explicitly inject it ourselves. To do that, we need to get a hold of the ServiceLocator (which is the main IoC container, kind of like ApplicationContext with Spring). Once we have the ServiceLocator, we can call locator.inject(anyObject) to explicitly resolve any injection dependencies.

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

The easiest place to get the ServiceLocator, when configuring the app, is in a Feature. Here we can also register Jersey components. Calling register on the FeatureContext (seen below) is just like calling env.jersey().register(...) with Dropwizard, it has the same effect. So we can do

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

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

You can see that explicitly inject the authenticator, with the call to locator.inject(authenticator). Then we register this feature through Dropwizard

env.jersey().register(new AuthenticatorFeature());

经过测试,可以正常工作.

Tested, and works fine.

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

Note, if you are wondering how it's possible to inject the HttpServletRequest, when there is no current request, it's because a proxy is injected. Same thing as if you were to inject the request into a Jersey filter, the same thing happens; a proxy is injected, as there is only a singleton filter, but the request changes from request to request, so a proxy needs to be injected.

另请参见: