Jersey实现Auth过滤器注入User对象遇UnsatisfiedDependencyException
org.glassfish.hk2.api.UnsatisfiedDependencyException in Jersey Token Auth Flow Let's break down your problem step by step—this is a common gotcha with HK2 (Jersey's DI container) when using event-driven user injection. Here's what to check and fix:
1. Verify Your @AuthenticatedUser Qualifier is Correctly Defined
First, make sure your custom qualifier annotation has all the required meta-annotations. HK2 won't recognize it if you're missing any:
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) public @interface AuthenticatedUser {}
@Qualifier: Marks this as a DI qualifier@Retention(RUNTIME): Ensures HK2 can see it at runtime@Target: Lets you use it on inject fields, method params, and producer methods
2. Fix Filter Execution Order
Your AuthorizationFilter is likely trying to inject the User before the AuthenticationFilter has validated the token and triggered the userAuthenticatedEvent. Fix this with Jersey's priority annotations to enforce execution order:
// AuthenticationFilter runs FIRST (higher priority) @Provider @Priority(Priorities.AUTHENTICATION) public class AuthenticationFilter implements ContainerRequestFilter { @Inject private EventBus eventBus; @Override public void filter(ContainerRequestContext ctx) throws IOException { // Validate token, fetch User from DB, etc. User authenticatedUser = validateTokenAndGetUser(ctx); // Publish event to trigger User creation eventBus.publish(new UserAuthenticatedEvent(authenticatedUser)); } } // AuthorizationFilter runs AFTER authentication @Provider @Priority(Priorities.AUTHORIZATION) public class AuthorizationFilter implements ContainerRequestFilter { @Inject @AuthenticatedUser private User currentUser; @Override public void filter(ContainerRequestContext ctx) throws IOException { // Check permissions using currentUser if (!hasAccess(currentUser, ctx)) { ctx.abortWith(Response.status(Response.Status.FORBIDDEN).build()); } } }
Priorities.AUTHENTICATION (1000) has a higher priority than Priorities.AUTHORIZATION (2000), so the auth filter runs first every time.
3. Ensure Your AuthenticatedUserProducer is Configured Properly
Your producer needs to be request-scoped (since each request has a unique user) and correctly listen for the authentication event:
@RequestScoped public class AuthenticatedUserProducer { private User authenticatedUser; // Listens for the authentication event public void onUserAuthenticated(@Observes UserAuthenticatedEvent event) { this.authenticatedUser = event.getUser(); } // Produces the User instance for injection @Produces @AuthenticatedUser @RequestScoped public User getAuthenticatedUser() { return authenticatedUser; } }
@RequestScoped: Ensures a fresh producer instance per request (avoids sharing users across requests)@Observes: Tells HK2 this method listens for theUserAuthenticatedEvent- The producer method also needs
@RequestScopedto tie the User instance to the current request lifecycle
4. Confirm HK2 is Scanning Your Producer and Filters
Even with bean-discovery-mode="all" in beans.xml, you need to make sure Jersey is scanning the packages containing your components:
- If you're using a
ResourceConfigclass:public class MyApiApplication extends ResourceConfig { public MyApiApplication() { // Scan all packages with your filters, producers, and resources packages("com.yourcompany.api.auth", "com.yourcompany.api.resources"); // Explicitly register filters if automatic scanning isn't working register(AuthenticationFilter.class); register(AuthorizationFilter.class); } } - If using
web.xml, add this init-param to your Jersey servlet:<init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.yourcompany.api</param-value> </init-param>
5. Check Your Maven Dependencies
Make sure you have all required HK2/Jersey dependencies (match version 2.30.1 with your Jersey installation):
<dependencies> <!-- Jersey Core Servlet Container --> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.30.1</version> </dependency> <!-- HK2 DI Integration for Jersey --> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>2.30.1</version> </dependency> <!-- HK2 API (required for events and qualifiers) --> <dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>hk2-api</artifactId> <version>2.6.1</version> <!-- Matches Jersey 2.30.1's bundled HK2 version --> </dependency> </dependencies>
Missing jersey-hk2 is a frequent cause of DI failures in Jersey 2.x.
6. Debug Event Publishing
Add logging to your AuthenticationFilter and AuthenticatedUserProducer to confirm:
- The
EventBusis not null in the auth filter - The
onUserAuthenticatedmethod is actually being called when a valid token is sent
If the event isn't being received, your producer can't create the User instance, leading directly to the injection error.
Common Pitfalls to Avoid
- Singleton Scope: Never use
@Singletonfor your producer or User instance—this will share the same user across all requests, leading to security issues and injection failures. - Typos: Double-check that you're using
@AuthenticatedUserconsistently (no spelling mistakes in the qualifier annotation or injection points). - Name Binding Conflicts: If you're using name-binding annotations (e.g.,
@Secured) on your filters, ensure they're applied correctly to both filters and protected resources—though this shouldn't cause injection failures directly, it can prevent filters from running at all.
内容的提问来源于stack exchange,提问作者Puru Vaish

