代码之家  ›  专栏  ›  技术社区  ›  tyro

在post方法spring引导的情况下,对经过身份验证的rest web服务的调用失败

  •  0
  • tyro  · 技术社区  · 7 年前

    我正在尝试使用一个rest web服务 在Httpmethod为POST的spring boot应用程序中,

    下面我将展示所有设置如何使用HttpMethod.GET的已验证web服务,以及我尝试使用HttpMethod.POST的相同已验证web服务并引发401个未授权错误的更改,

    RestTemplateFactory获取restTemplate,

       public class RestTemplateFactory implements FactoryBean<RestTemplate>, InitializingBean {
    
            @Autowired
            private RestTemplate restTemplate;
    
            public RestTemplate getObject() {
                return restTemplate;
            }
            public Class<RestTemplate> getObjectType() {
                return RestTemplate.class;
            }
            public boolean isSingleton() {
                return true;
            }
    
            public void afterPropertiesSet() {
                HttpHost host = new HttpHost("localhost", 9090, "http");
                restTemplate = new RestTemplate(
                        new HttpComponentsClientHttpRequestFactoryBasicAuth(host));
            }
        }
    

    对于基本身份验证,

    public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory {
    
            HttpHost host;
    
            public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) {
                super();
                this.host = host;
            }
    
            protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
                return createHttpContext();
            }
    
            private HttpContext createHttpContext() {
                AuthCache authCache = new BasicAuthCache();
    
                BasicScheme basicAuth = new BasicScheme();
                authCache.put(host, basicAuth);
    
                BasicHttpContext localcontext = new BasicHttpContext();
                localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
                return localcontext;
            }
        }
    

     public ResponseEntity<SomeResponse> consumeRestApi(SomeRequest request) throws InvalidDataException {
            ResponseEntity<SomeResponse> responseEntity = null;
            try {
                RestTemplate restTemplate = restTemplateFactory.getRestTemplate();
                restTemplate
                        .getInterceptors()
                        .add(new BasicAuthorizationInterceptor(username, pwd));
    
                responseEntity = restTemplate.exchange("http://localhost:9090/sendMail?phone=60598745&email=abc@gmail.com", HttpMethod.GET, null, SomeResponse.class);
            } catch (Exception e) {
               // Exception handing...
            }
            return responseEntity;
        }
    

    我有一个运行在本地主机上的虚拟服务器,使用HttpMethod.Get,这是我在上述设置中尝试使用的经过身份验证的服务,

    @RequestMapping(value = "/sendMail", method = RequestMethod.GET)
    public ResponseEntity<SomeResponse> sendmail(@RequestParam String phone, @RequestParam String email){
    
        SomeResponse response = SomeResponse.builder()
                .id("101")
                .type("formdata")
                .fieldValues(getFieldValues(phone,email))
                .build();
    
        return new ResponseEntity<>(response,HttpStatus.CREATED);
    
    }
    

    当它是HttpMethod.GET方法时,它在上面提到的所有设置中都能很好地工作,

    下面是我尝试过的更改,但它返回了401的错误,即未经授权的错误

    我尝试的post方法的改变,

    通过保持 RestTemplateFactory HttpComponentsClientHttpRequestFactoryBasicAuth

    我首先更改,虚拟服务器上的rest api接受POST-so请求,

    @RequestMapping(value = "/sendMail", method = RequestMethod.POST)
        public ResponseEntity<SomeResponse> sendmail(@RequestParam String phone, @RequestParam String email){
    // Same as above 
    }
    

    下一个更改是使用方法post调用方法,

    public ResponseEntity<SomeResponse> consumeRestApi(SomeRequest request) throws InvalidDataException {
                ResponseEntity<SomeResponse> responseEntity = null;
                try {
                    RestTemplate restTemplate = restTemplateFactory.getRestTemplate();
                    restTemplate
                            .getInterceptors()
                            .add(new BasicAuthorizationInterceptor(username, pwd));
    
                                SomeResponse response = restTemplate.postForObject("http://localhost:9090/sendMail?phone=60598745&email=abc@gmail.com",request, SomeResponse.class);
    
                } catch (Exception e) {
                   // Exception handling....
                    }
                }
                return new ResponseEntity<SomeResponse>(HttpStatus.CREATED);
            }
    

    有人能告诉我哪里出了问题吗,

    1 回复  |  直到 7 年前
        1
  •  1
  •   M. Deinum    7 年前

    我想问题在于您创建和配置 RestTemplate RestTemplateBuilder 建造 并且它有builder方法来做额外的配置。

    除此之外 rest模板 是线程安全的,因此您可以重用创建的实例,而不是重新创建以使用它。你的调用类可以被重构成这样

    public class EndpointTester {
    
      private final RestTemplate rest;
    
      public EndpointTester(RestTemplateBuilder rtb, String username, String pwd) {
        this.rest = rtb.basicAuthorization(username, pwd).build();
      }
    
      public ResponseEntity<SomeResponse> consumeRestApi(SomeRequest request) throws InvalidDataException {
            ResponseEntity<SomeResponse> responseEntity = null;
            try {             
                responseEntity = rest.postForEntity("http://localhost:9090/sendMail?phone=60598745&email=abc@gmail.com", null, SomeResponse.class);
            } catch (Exception e) {
               // Exception handing...
            }
            return responseEntity;
        }
    }
    

    这样你就不需要 RestTemplateFactory HttpComponentsClientHttpRequestFactoryBasicAuth 从而简化了配置和代码。