Reputation: 13038
I have created a Javae EE app using JAX-RS 2.0 and JPA. I created a special provider of my User entity (using Qualifiers) to provide the current user (logged in) as entity from applications user database. To get current user i use
@Context
private SecurityContext secContext;
The problem is that this is null. The security is setup fine (Wildfly 8.2) - the app asks for Authentication (basic) but SecurityContext
is null. Here is the code:
@RequestScoped
public class CurrentUserProducer implements Serializable {
/**
* Default
*/
private static final long serialVersionUID = 1L;
@Context
private SecurityContext secContext;
/**
* Tries to find logged in user in user db (by name) and returns it. If not
* found a new user with role {@link UserRole#USER} is created.
*
* @return found user a new user with role user
*/
@Produces
@CurrentUser
public User getCurrentUser() {
if (secContext == null) {
throw new IllegalStateException("Can't inject security context - security context is null.");
//... code to retrieve or create new user
return user;
}
}
As you see I check secContext
for null and i see my exception as soon as i try to reach a resource that injects @CurrentUser
.
So how to fix this? Why is SecurityContext
null.
Upvotes: 2
Views: 12144
Reputation: 209092
As stated in my comment
SecurityContext
is a JAX-RS component and can only be injected into other JAX-RS component. All you have is a CDI bean. You can try to make it an EJB and injectSessionContext
. See Securing an Enterprise Bean Programmatically
Haven't tested but seems to work for the OP. This is a EE stack solution.
Another JAX-RS (Resteasy specific) way to allow for injection is with the help of the ResteasyProviderFactory
(found with help from this answer). You could use this in a ContainerRequestFilter
, which has access to the SecurityContext
. We can use the RESTeasy utility class to push the User
into the context. This allows for injection with the @Context
annotation. Not sure how/if it would work with a custom annotation though. Here's an example
@Provider
public class UserContextFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext context) throws IOException {
SecurityContext securityContext = context.getSecurityContext();
String username = securityContext.getUserPrincipal().getName();
ResteasyProviderFactory.pushContext(User.class, new User(username));
}
}
Note: this is a JAX-RS 2.0 solution (i.e. RESTeasy 3.x.x). Prior to 2.0, there is no ContainerRequestFilter
Upvotes: 2
Reputation: 13038
I found another way to get the class recognized by Jax-Rs: Implementing ContextResolver and annotating the class with provider.
To implement the interface i added:
@Override
public User getContext(Class<?> type) {
if (type.equals(User.class)){
return getCurrentUser();
}
return null;
}
I am not sure but probably with this i can do
@Context private User currentUser;
But i didn't try. But the injection via qualifier is working now (security context is injected).
Upvotes: 0