将spring-boot 1.5迁移到2.0后,Webservices上的405错误

问题描述 投票:1回答:2

我的弹簧配置知识不足,我无法解决的问题:每个GET返回错误404和每个POST返回错误405。我的spring安全过滤器运行良好,但是没有调用@PostMapping或@GetMapping注释方法。我已经将旧属性server.context-path重命名为新名称server.servlet.context-path,但是它仍然无法正常工作。我使用undertow网络服务器:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
    <version>${springBoot.version}</version>
</dependency>

我的app.properties文件实际上名为application.mssql.properties:

## Hibernate properties
... some properties ...

##Spring boot properties
server.servlet.context-path =/my-context

并且此服务器实例配置在我的ApplicationConfiguration中:

@SpringBootApplication(scanBasePackages = { 
    "t.i.DAO", 
    "t.i.SERVICES",
    "t.i.config", 
    "t.i.config.security" })
@PropertySource({ "classpath:application.mssql.properties" })
@EnableCaching
@EnableTransactionManagement
public class ApplicationConfiguration {

    // Properties of application.mssql.properties file
    @Autowired
    private Environment env;

    ... some code there...

   @Bean
   public ConfigurableServletWebServerFactory undertowServerInstance() { 
        UndertowServletWebServerFactory customizer = new UndertowServletWebServerFactory();
        customizer.addBuilderCustomizers((builder) -> {
            builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
        });

        // EDIT: add: set the context by reading app.properties
        customizer.setContextPath(env.getProperty("server.servlet.context-path"));
        return customizer;
   }
}

注意,在我的旧版spring 1.5配置中,undertowServerInstance()方法是不同的:

@Bean
public EmbeddedServletContainerCustomizer undertowServerInstance() {
    return (container) -> {
        if(container instanceof UndertowEmbeddedServletContainerFactory) {
            ((UndertowEmbeddedServletContainerFactory) container)
                .addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
        }
    };
}

我像这样使用Spring安全配置类SecurityConfig:

package t.i.config;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // allows AOP @PreAuthorize and some other annotations to be applied to methods.
@EnableWebSecurity
@EnableScheduling // allows to run Spring schedulers and periodically run some tasks. We use scheduler for evicting EhCache tokens.
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ... some code for security configuration ...

        // adding authentication filter
        http.addFilterBefore(new AuthenticationFilter(this.authenticationManager), BasicAuthenticationFilter.class);

    }
}

此类用于从用户凭据生成新令牌,或者检查令牌是否存在于标头中(对于每个请求都会调用此过滤器,并且该过滤器仍然有效):

package t.i.config.security;

public class AuthenticationFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        try {
            // check or create token. Exception if credentials or token invalid
        }
        catch(AuthenticationException authenticationException){
            ((HttpServletResponse) http).sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
            return;
        }

        chain.doFilter(request, response);
    }
}

这是我的WebMvcConfig,其中包含@RestController类的程序包位置(编辑:添加了实现WebMvcConfigurer):

package t.i.config;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"t.i.controllers"})
public class WebMvcConfig implements WebMvcConfigurer {
 ... code there ... 
}

例如,当我调用/api/authenticate URL时,将调用我的spring身份验证过滤器方法并创建令牌,但是从不调用此WS(而是返回405:]

package t.i.controllers;

@RestController
public class AuthenticationController {


    @PostMapping("api/authenticate")
    public UserDTO authenticate(AuthenticationWithToken principal) {

        ... some code there that is never called with spring boot 2.0 ...

        return userDTO;
    }
}

我仍然不了解这个问题,我认为Undertow配置中缺少某些内容。

编辑:在ApplicationConfiguration.undertowServerInstance()方法中,如果我删除该行:

// EDIT: add: set the context by reading app.properties
customizer.setContextPath(env.getProperty("server.servlet.context-path"));

然后不再触发AuthenticationFilter。使用Spring Boot 1.5,我不需要显式指定Undertow上下文。

编辑:我将身份验证WS方法更改为GET:

 package t.i.CONTROLLERS;

@RestController
public class AuthenticationController {

    @RequestMapping(value = "/api/authenticate", method = RequestMethod.GET)
    public UserDTO authenticate(AuthenticationWithToken principal) {

        ... some code there that is still never called with spring boot 2.0 ...

        return userDTO;
    }
}

身份验证过滤器运行良好,但方法AuthenticationController.authenticate仍未调用。这是我使用chrome调试器得到的:

Error 404 with Get request authentication

摘要:

  • 我在获取请求时遇到404错误,在发布时出现405错误
  • Undertow需要明确设置上下文,否则将不调用我的身份验证过滤器
就像spring不处理我的任何@RestController一样,但是它们仍然实例化(我使用控制台打印将它们测试到构造函数中)。

EDIT:现在可以在Spring Boot 2.1.8中使用。发布! (我不知道从哪个春季启动版本开始工作,因为我从春季启动1.5.7.RELEASE切换到了2.1.8.RELEASE)

java spring spring-boot undertow
2个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.