Аутентификация с использованием контекста области запроса с Spring

Я пытаюсь создать пользовательский «userContext» как SpringBean с областью запроса, но я не могу сделать это. В основном у меня есть REST api Jersey, и я хочу сделать аутентификацию и авторизацию с помощью моих пользовательских фильтров, в которых я автоматически подключаю свой «userContext». Процесс выглядит следующим образом:

  1. REST API вызван (я ожидаю, что Spring создаст новый экземпляр UserContext bean)
  2. AuthenticationFilter автоматически запускает новый экземпляр userBean и заполняет его
  3. AuthorizationFilter автоматически запускает тот же экземпляр, который заполняется сейчас, и авторизует пользователя

Когда я первый раз вызываю REST api (после перезапуска сервера), он работает как и ожидалось, но любой другой вызов не удается, потому что AutorizationFilter получает пустой экземпляр юзербары. Я ожидаю некоторого фундаментального непонимания областей с моей стороны.

Btw: я хотел бы избежать использования ThreadLocal напрямую, так как область запроса должна заботиться об этом

Я хотел бы знать, почему authorizationFilter не видит заполненную версию userBean и почему первый вызов работает. Заранее спасибо за любую помощь.

Только некоторые части кода:

@Secured({Role.ADMIN}) //custom annotation
@GET
@Path("{id}")
public Response getUserById(@PathParam("id") Long id) throws IOException, MainException {

@Secured //custom annotation
@Provider
@Priority(Priorities.AUTHENTICATION)
@Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
public class AuthenticationFilter implements ContainerRequestFilter 
    @Autowired
    private User userContext;


@Secured //custom annotation
@Provider
@Priority(Priorities.AUTHORIZATION)
@Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
public class AuthorizationFilter implements ContainerRequestFilter {
    @Autowired
    private User userContext;


@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Component
@Scope(value = "request",  proxyMode = ScopedProxyMode.TARGET_CLASS)
public class User extends ModelBase implements Serializable {

1 ответ

  1. Так как поставщики не имеют области запроса, мне пришлось ввести весь ApplicationContext, чтобы я мог непосредственно изменить правильный экземпляр UserContext bean (который является областью запроса). В основном я сделал что-то подобное в обоих фильтрах:

    @Autowired
    private ApplicationContext applicationContext;
    
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
    
        User userBean=applicationContext.getBean(User.class);
        ....
        userBean.setSomething("aaa");
    

    Тогда я мог бы просто autowire такой боб в моих ресурсах REST, потому что они ограничены запросом defaul:

    @Component
    @Api(value="/users", description = "Endpoint for Users listing")
    @Consumes({MediaType.APPLICATION_JSON, Constants.API_VERSIONS.V1_HEADER_XML, Constants.API_VERSIONS.V1_HEADER_JSON})
    @Produces({MediaType.APPLICATION_JSON, Constants.API_VERSIONS.V1_HEADER_XML, Constants.API_VERSIONS.V1_HEADER_JSON})
    @Path("/users")
    public class UserResource {
    
        private static final Logger logger = LoggerFactory.getLogger(UserResource.class);
    
        @Autowired
        private User authenticatedUser;
    

    Это решение должно быть жизнеспособным и устойчивым к условиям гонки потоков и т.д.