Я хочу проверить пользователя, делающего запрос. Для этого у меня есть два фильтра: AuthenticationFilter и AuthorizationFilter. AuthenticationFilter извлекает токен из запроса и находит пользователя из базы данных. AuthorizationFilter проверяет, имеет ли этот пользователь (полученный предыдущим фильтром) необходимые разрешения. У меня есть два возможных решения, и я хотел бы знать плюсы и минусы каждого из них, и какие я должен использовать. Мне также нужно было бы получить доступ к пользователю в реальной бизнес-логике. Мой код выглядит следующим образом:
AuthenticationFilter:
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
// option 1.1
@Inject
@AuthenticatedUser
private Event<User> authenticatedUserEvent;
// option 1.2
@Inject
@AuthenticatedUser
private User authenticatedUser;
public void filter(ContainerRequestContext requestContext) throws IOException {
String token = getToken(requestContext);
User user = getUser(token)
if (user == null) {
requestContext.abortWith(...);
} else {
// option 1.1
authenticatedUserEvent.fire(User);
// option 1.2
authenticatedUser.setData(user);
// option 2
requestContext.setProperty("authenticatedUser", user);
}
}
}
AuthorizationFilter:
@Secured
@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
@Context
private ResourceInfo resourceInfo;
// option 1
@Inject
@AuthenticatedUser
private User authenticatedUser;
public void filter(ContainerRequestContext requestContext) throws IOException {
// option 2
User authenticatedUser = (User) requestContext.getProperty("authenticatedUser")
boolean allowed = verifyRoles(user, resourceInfo.getResourceClass(), resourceInfo.getResourceMethod());
if (!allowed) {
requestContext.abortWith(...);
}
}
}
AuthenticatedUserProducer (только для варианта 1):
@RequestScoped
public class AuthenticatedUserProducer {
@Produces
@RequestScoped
@AuthenticatedUser
private User authenticatedUser;
public void handleAuthenticationEvent(@Observes @AuthenticatedUser User user) {
this.authenticatedUser = user
}
}
Для варианта 1 необходимо пометить фильтры с помощью @RequestScoped
? По умолчанию фильтры ограничены областью применения, поэтому безопасна ли инъекция? То есть событие, инициируемое фильтром 1 в цепочке запросов 1, не будет в конечном итоге введено в фильтр 2 цепочки 2, если обрабатывается более одного запроса одновременно? И то же самое при внедрении пользователя в класс ресурсов, где работает настоящая бизнес-логика?
Для варианта 2 у меня больше нет доступа к ContainerRequestContext
, но я могу получить доступ к объекту, введя HttpServletRequest
. Но эта опция кажется мне «менее чистой», потому что мне нужно привести сохраненные объекты к Пользователю, прежде чем использовать их, когда с помощью инъекционного подхода я могу использовать объекты напрямую.
Я уже проверил эти вопросы, что я ищу, чтобы определить, какой вариант является лучшим:
В настоящее время я использую WildFly 11 с его реализацией по умолчанию JAX-RS (Resteasy) и CDI (Weld).