Spring Cloud 应用程序中具有 Forbidden 状态的微服务请求响应

Posted

技术标签:

【中文标题】Spring Cloud 应用程序中具有 Forbidden 状态的微服务请求响应【英文标题】:inter micro-service request responds with Forbidden status in spring cloud application 【发布时间】:2018-10-27 12:22:18 【问题描述】:

我正在研究微服务架构。我选择了spring cloud框架。

我的应用程序 shema 如下所示:

我也有发现服务器 eureka,但我决定跳过图片以简化它。

示例的完整源代码可以在 githib 上找到: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 serviceindex.html 页面,当我尝试访问它时 - 身份验证流程成功发生,最终此应用程序成功登录。然后我尝试从hello world service 执行方法/hello 并看到响应:

"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

问题

    如何解决此问题? 在上一点修复之后,我想知道如何执行对该服务的授权请求。换句话说,我想在 hello 服务上启用 oauth 2 授权,并有可能从 hello world service 发出请求

【问题讨论】:

您是否尝试过使用OAuth2RestTemplate 而不是普通的RestTemplate?在此处查看示例***.com/questions/27864295/… 【参考方案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);

    在 SpringBoot Application 类中添加 oauth2FeignRequestInterceptor

@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());
            
        ;
    
    在 SpringBoot Application 类中添加几个注解

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

希望对您有所帮助。

【讨论】:

所有与hello world服务应用相关的代码? 另外我不能说我需要 Feign。我现在对 restTemplate 很满意 是的,和hello world相关的服务代码应该放在HelloWorldStarter附近 restTemplate 内部没有任何身份验证逻辑,另一方面 oauth2FeignRequestInterceptor 包含它。 docs.spring.io/spring-security/oauth/apidocs/org/… 这个呢?

以上是关于Spring Cloud 应用程序中具有 Forbidden 状态的微服务请求响应的主要内容,如果未能解决你的问题,请参考以下文章

如何允许 Spring Boot 应用程序使用具有 Spring Cloud 依赖关系的自定义 jar

Spring Cloud教程加密和解密

Spring Cloud : 配置管理

spring cloud Config--server

spring cloud互联网分布式微服务云平台规划分析--spring cloud服务统一配置中心

spring cloud互联网分布式微服务云平台规划分析--spring cloud服务统一配置中心