Запрос между микросервисами отвечает статусом "Запрещено" в облачном приложении Spring

Я исследую микросервисную архитектуру. Я выбрал весенний облачный каркас.

Схема моего приложения выглядит так:

Запрос между микросервисами отвечает статусом "Запрещено" в облачном приложении Spring

Также у меня есть сервер обнаружения eureka, но я решил пропустить картинку, чтобы упростить ее.

Полный исходный код примера вы можете найти на гитибе: https://github.com/gredwhite/spring-cloud

Объяснение проблемы:

привет мировой сервис:

@GetMapping("/helloWorld")
@HystrixCommand(fallbackMethod = "reliable")
public String hello() {
    return this.restTemplate.getForObject("http://hello-service/hello?name=World", String.class);
}

привет сервис:

@GetMapping("/hello")
public String hello(@RequestParam("name") String name) throws UnknownHostException, InterruptedException {           
     return "Hello " + name + "!";
 }

Когда я запустил hello service и попытался получить доступ к localhost:8082/h/hello?name=Vasya (/h - контекстный путь) - запрос выполняется успешно, и я вижу сообщение Hello Vasya в ответе. Я должен сказать, что для этой службы отключена аутентификация.

hello world service имеет страницу index.html, и когда я пытаюсь получить к ней доступ, процесс аутентификации выполняется успешно, и в конечном итоге это приложение успешно входит в систему. Затем я пытаюсь выполнить метод /hello из hello world service и вижу ответ:

{"timestamp":"2018-05-17T08:53:04.623+0000","status":403,"error":"Forbidden","message":"Forbidden","path":"/hw/helloWorld"}

Конфигурация Oauth2:

привет мировой сервис

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "say-hello")
@EnableAutoConfiguration
@EnableOAuth2Sso
public class HelloWorldStarter {

    public static void main(String[] args) {
        SpringApplication.run(HelloWorldStarter.class, args);
    }


    @RestController
    @EnableDiscoveryClient
    @EnableCircuitBreaker
    public static class HelloWorldController {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private DiscoveryClient discoveryClient;

        @GetMapping("/helloWorld")
        @HystrixCommand(fallbackMethod = "reliable")
        public String hello() {           
            return this.restTemplate.getForObject("http://hello-service/hello?name=World", String.class);
        }

        public String reliable() {
            return "Could not get response from service";
        }
    }

    @org.springframework.context.annotation.Configuration
    public static class Configuration {
        @Bean
        @LoadBalanced
        RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
}

application.yml:

spring:
  application:
    name: hello-world-service
server:
  port: 8081
  servlet:
    context-path: /hw
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka
  instance:
    preferIpAddress: true

security:
  oauth2:
    client:
      client-id: acme
      client-secret: acmesecret
      access-token-uri: http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/me

logging:
  level:
    org.springframework.security: DEBUG
    org.springframework.web: DEBUG

Вопросов

  1. Как я могу исправить эту проблему?
  2. После исправления предыдущего пункта я хочу знать, как выполнить авторизованный запрос к этой службе. Другими словами, я хочу включить авторизацию oauth 2 для службы приветствия и иметь возможность делать запрос от hello world service.

Вы пробовали использовать OAuth2RestTemplate вместо обычного RestTemplate? см. пример здесь stackoverflow.com/questions/27864295/…

KSTN 21.05.2018 18:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
2 332
1

Ответы 1

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

Предлагаю вам следующее решение:

  1. Создайте сервис FeignClient.

@FeignClient(name = "hello-service", url = "http://hello-service")
public interface HelloService {

    @RequestMapping(method = RequestMethod.GET, value = "/hello")
    String hello(@PathVariable("name") String name);

}
  1. Добавить oauth2FeignRequestInterceptor в класс SpringBoot Application

@Bean
    public RequestInterceptor oauth2FeignRequestInterceptor() {
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();

                requestTemplate.header("Authorization", "bearer " + details.getTokenValue());
            }
        };
    }
  1. Добавьте несколько аннотаций в свой класс SpringBoot Application

@EnableOAuth2Client
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableFeignClients
public class HelloWorldStarter

Надеюсь, это поможет.

весь код, связанный с приложением службы hello world?

gstackoverflow 17.05.2018 16:01

К тому же я не могу сказать, что мне нужен Feign. Я доволен restTemplate на данный момент

gstackoverflow 17.05.2018 16:21

да, это связано с кодом службы hello world, его следует разместить рядом с HelloWorldStarter

Alexander Petrov 17.05.2018 16:27

restTemplate не имеет внутри логики аутентификации, с другой стороны, oauth2FeignRequestInterceptor содержит ее.

Alexander Petrov 17.05.2018 16:29

А что насчет этого docs.spring.io/spring-security/oauth/apidocs/org/…?

gstackoverflow 17.05.2018 16:36

Как видите, служба приветствия не защищена. Почему я вижу "Запрещено"?

gstackoverflow 17.05.2018 17:27

Другие вопросы по теме