Переадресация заголовков запросов на несколько вызовов сервисов в Spring + Netflix + Feign - PullRequest
0 голосов
/ 17 декабря 2018

У меня в приложении есть несколько промежуточных и базовых сервисов.Все сервисы Spring Boot и используют библиотеку Netflix.Когда пользователь запрашивает информацию, запрос передаст / может передать другие службы в цепочке, например:

Client <-> Zuul <-> Service B <-> Service A

Я настроил все службы (A и B) как ResourceServer, так что каждый доступ должен быть аутентифицирован.При запросе токена доступа (с сервера Spring Security Server) и использовании его для запроса информации непосредственно из службы A все работает нормально.Когда я использую тот же токен для доступа к информации из службы B (для которой требуется служба A в дальнейшем), я получаю сообщение об ошибке «HTTP 401: требуется полная аутентификация».Служба B использует FeignClient для вызова службы А.

После некоторой отладки я обнаружил, что заголовок авторизации не передается из службы B в службу А. Служба B правильно проверяет сам токен и предоставляет доступ кметод и пытается выполнить запрос службы А.

Я пытался RequestInterceptor, но безуспешно (Ошибка «Область« запрос »не активен для текущего потока»)

@Component
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_TOKEN_TYPE = "Bearer";
    private final OAuth2ClientContext oauth2ClientContext;

    public OAuth2FeignRequestInterceptor(OAuth2ClientContext oauth2ClientContext) {
        Assert.notNull(oauth2ClientContext, "Context can not be null");
        this.oauth2ClientContext = oauth2ClientContext;
    }

    @Override
    public void apply(RequestTemplate template) {
        if (template.headers().containsKey(AUTHORIZATION_HEADER)) {
            ...
        } else if (oauth2ClientContext.getAccessTokenRequest().getExistingToken() == null) {
            ...
        } else {
            template.header(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE,
                    oauth2ClientContext.getAccessTokenRequest().getExistingToken().toString()));
        }
    }
}

Это пример прокси-функции, которая использует FeignClient:

@Autowired
private CategoryClient cat;


@HystrixCommand(fallbackMethod = "getAllFallback", commandProperties = {@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2") })
@GetMapping("/category")
public ResponseEntity<List<Category>> getAll() {
    try {
        ResponseEntity<List<Category>> categories = this.cat.getAll();
        ...
        return categories;
    } catch(Exception e) {
        ...
    }
}

Есть ли какое-либо рабочее решение для передачи заголовка авторизации от прокси-функции в FeignClient, чтобы служба A получала заголовок и могла выполнятьсвоя проверка подлинности с ним?

1 Ответ

0 голосов
/ 19 декабря 2018

Нашел рабочее решение.Я до сих пор не знаю, является ли это «лучшим» способом сделать это, и если у кого-то есть лучшее решение, я буду рад, если вы поделитесь им.Но пока это работает как ожидалось:

@Bean
public RequestInterceptor requestTokenBearerInterceptor() {

    return new RequestInterceptor() {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
            requestTemplate.header("Authorization", "Bearer " + details.getTokenValue());                   
        }
    };
}
...