Spring Boot 重复的端点

huangapple go评论76阅读模式
英文:

Spring Boot Duplicated Endpoints

问题

第一件需要澄清的事情可能是标题可能不太具体,但我不知道如何更好地表达,因为我不理解我遇到的问题。

一点背景:
我有一个使用JWT身份验证和安装了Swagger的Spring Boot应用程序。

我作为示例使用的控制器具有以下内容。

@RestController
@RequestMapping("/api/v1")
@CrossOrigin(origins = "*")
@Api(value = "Operations Dummy")
public class DummyController {

    @Autowired
    IDummyService _IDummyService;

    @ApiOperation(value = "Get All Dummy")
    @GetMapping("/dummy")
    public ResponseEntity<ResultList<DummyDTO>> getAllDummy() {
        return _IDummyService.getAll();
    }

}

像这样的控制器有好几个,都类似。

应用程序的正确运行方式是调用端点 GET http://localhost:8080/api/v1/dummy

响应将类似于以下内容:

{
  "data": [
    {
      "id": 0,
      "name": "test"
    },
    {
      "id": 1,
      "name": "dummy"
    }
  ],
  "metadata": {
    "count": 0
  }
}

问题是,一些端点可以从根目录访问,如下所示:GET http://localhost:8080/dummy

它们会产生不同的响应,但仍然显示数据

{
  "_embedded" : {
    "dummy" : [ {
      "id" : "0",
      "name" : "test",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080A/dummy/0"
        }
    },{
      "id" : "1",
      "name" : "dummy",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/dummy/1"
        }
    } ]
  },
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/dummy"
    },
    .
    .
    .
  },
  "page" : {
    "size" : 20,
    "totalElements" : 32,
    "totalPages" : 2,
    "number" : 0
  }
}

有关更多信息,这是配置文件的副本:

@Override
protected void configure(HttpSecurity http) throws Exception {
	
	http.cors().and().csrf().disable().        		
    authorizeRequests()
    .antMatchers("/api/v1/users/auth").permitAll()
    .antMatchers("/error",
    		"/v2/api-docs",
            "/configuration/ui",
            "/swagger-resources/**",
            "/configuration/**",
            "/swagger-ui.html",
            "/webjars/**").permitAll()
    .antMatchers("/api/v1/**").authenticated()
    .and()
    .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
    http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}

正如我所说,并非每个控制器都会出现这种情况,实际上,当我意识到这个问题时,我删除了虚拟控制器并重新编译了项目,但仍然可以通过/dummy获取信息,而不是通过/api/v1/dummy

至于日志,在调用/dummy时会产生以下日志:

o.s.web.servlet.DispatcherServlet        : GET "/dummy", parameters={}
m.m.a.RequestResponseBodyMethodProcessor : Using 'application/hal+json;q=0.8', ...
m.m.a.RequestResponseBodyMethodProcessor : Writing [PagedResource { content: 
o.s.web.servlet.DispatcherServlet        : Completed 200 OK

而对于对/api/v1/dummy的调用,则是:

s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.es.controller.DummyController#getAllDummy()
o.s.web.servlet.DispatcherServlet        : GET "/api/v1/dummy", parameters={}
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.es.controller.DummyController#getAllDummy()
o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [com.example.es.util.ResultList@19771362]
o.s.web.servlet.DispatcherServlet        : Completed 200 OK

更新:

我在application.properties文件中添加了以下行,似乎现在确实返回404,但我不确定这是否会影响操作。

spring.data.rest.detection-strategy=annotated
英文:

The first thing to clarify is that perhaps the title is not very concrete but I do not know how to express it better because I do not understand the problem I have.

A little bit of context:
I have a Spring Boot application with JWT authentication and Swagger installed.

The controller I am using as an example has the following content.

@RestController
@RequestMapping(&quot;/api/v1&quot;)
@CrossOrigin(origins = &quot;*&quot;)
@Api(value = &quot;Operations Dummy&quot;)
public class DummyController {

    @Autowired
	IDummyService _IDummyService;

    @ApiOperation(value = &quot;Get All Dummy&quot;)
    @GetMapping(&quot;/dummy&quot;)
    public ResponseEntity&lt;ResultList&lt;DummyDTO&gt;&gt; getAllDummy() {
		return _IDummyService.getAll();
    }

}

Like this controller there are several, all similar.

The correct functioning of the application would be to call the endpoint GET http://localhost:8080/api/v1/dummy

The response would be similar to the following:

{
  &quot;data&quot;: [
    {
      &quot;id&quot;: 0,
      &quot;name&quot;: &quot;test&quot;
    },
    {
      &quot;id&quot;: 1,
      &quot;name&quot;: &quot;dummy&quot;
    }
  ],
  &quot;metadata&quot;: {
    &quot;count&quot;: 0
  }
}

The problem is that some of the endpoints are accessible from the root, as follows: GET http://localhost:8080/dummy

And they produce a different response, but still show the data

{
  &quot;_embedded&quot; : {
    &quot;dummy&quot; : [ {
      &quot;id&quot; : &quot;0&quot;,
      &quot;name&quot; : &quot;test&quot;,
      &quot;_links&quot; : {
        &quot;self&quot; : {
          &quot;href&quot; : &quot;http://localhost:8080A/dummy/0&quot;
        }
    },{
      &quot;id&quot; : &quot;1&quot;,
      &quot;name&quot; : &quot;dummy&quot;,
      &quot;_links&quot; : {
        &quot;self&quot; : {
          &quot;href&quot; : &quot;http://localhost:8080/dummy/1&quot;
        }
    } ]
  },
  &quot;_links&quot; : {
    &quot;first&quot; : {
      &quot;href&quot; : &quot;http://localhost:8080/dummy&quot;
    },
    .
    .
    .
  },
  &quot;page&quot; : {
    &quot;size&quot; : 20,
    &quot;totalElements&quot; : 32,
    &quot;totalPages&quot; : 2,
    &quot;number&quot; : 0
  }
}

For more information this is a copy of the configuration file:

@Override
protected void configure(HttpSecurity http) throws Exception {
	
	http.cors().and().csrf().disable().        		
    authorizeRequests()
    .antMatchers(&quot;/api/v1/users/auth&quot;).permitAll()
    .antMatchers(&quot;/error&quot;,
    		&quot;/v2/api-docs&quot;,
            &quot;/configuration/ui&quot;,
            &quot;/swagger-resources/**&quot;,
            &quot;/configuration/**&quot;,
            &quot;/swagger-ui.html&quot;,
            &quot;/webjars/**&quot;).permitAll()
    .antMatchers(&quot;/api/v1/**&quot;).authenticated()
    .and()
    .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    
    http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}

As I said, not with every controller this happens, in fact, when I realized that this problem was happening, I deleted the dummy controller and compiled the project again, and it was still possible to get the information through /dummy and not through /api/v1/dummy

As for the logs, when we call /dummy the following log is produced:

o.s.web.servlet.DispatcherServlet        : GET &quot;/dummy&quot;, parameters={}
m.m.a.RequestResponseBodyMethodProcessor : Using &#39;application/hal+json;q=0.8&#39;, ...
m.m.a.RequestResponseBodyMethodProcessor : Writing [PagedResource { content: 
o.s.web.servlet.DispatcherServlet        : Completed 200 OK

while for the call to /api/v1/dummy it is:

s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.es.controller.DummyController#getAllDummy()
o.s.web.servlet.DispatcherServlet        : GET &quot;/api/v1/dummy&quot;, parameters={}
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.es.controller.DummyController#getAllDummy()
o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using &#39;application/json&#39;, given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [com.example.es.util.ResultList@19771362]
o.s.web.servlet.DispatcherServlet        : Completed 200 OK

Update:

I have added the following line in the application.properties file and it seems that now it does return 404, but I am not sure if this can affect the operation

spring.data.rest.detection-strategy=annotated

答案1

得分: 1

因为您正在使用 spring-data-rest starter,它在幕后执行了许多操作。

比如 -

  • 使用HAL作为媒体类型,为您的领域模型公开了一个可发现的REST API。

  • 公开代表您的模型的集合、项和关联资源。

基本上,您的所有存储库和集合都会以API的形式被公开。

默认情况下,Spring Data REST会在根URI('/')上提供REST资源。这就是为什么您能够在 http://localhost:8080/dummy 上获得响应。

您可以通过在 application.properties 中设置 spring.data.rest.basePath 来更改此根路径。

因此,如果您将其设置为 spring.data.rest.basePath=/pablo,那么您将无法在 http://localhost:8080/dummy 上获得响应数据。而是会在 http://localhost:8080/pablo/dummy 上获得响应。

一些有用的文档:

https://docs.spring.io/spring-data/rest/docs/3.3.4.RELEASE/reference/html/#reference

英文:

Since you are using spring-data-rest starter it does a lot of things behind the scenes.

Such as -

  • Exposes a discoverable REST API for your domain model using HAL as media type.

  • Exposes collection, item and association resources representing your model.

Basically all your repositiories and collections are exposed as APIs.

By default, Spring Data REST serves up REST resources at the root URI, '/'. That is why you are able to get response for http://localhost:8080/dummy.

You can this root by setting spring.data.rest.basePath in application.properties.

So if you set it to spring.data.rest.basePath=/pablo then you won't get response data for http://localhost:8080/dummy. Instead you will get response on http://localhost:8080/pablo/dummy

Some useful docs :-

https://docs.spring.io/spring-data/rest/docs/3.3.4.RELEASE/reference/html/#reference

huangapple
  • 本文由 发表于 2020年10月20日 03:47:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64434229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定