Spring Boot - 不允许使用POST方法

11

我希望你能帮忙翻译一下这个问题... 我有一个使用Spring Boot应用程序,它具有S2S通信功能。我有一个@RestController方法,应该接受POST请求。

以下是控制器:

@RestController
public class PaymentRestController {

@PostMapping("/util/paymentResponse")
    public void savePaymentResponse(@RequestParam boolean transaction_status, @RequestParam String usedToken,
            @RequestParam String transaction_message, @RequestParam String authCode,
            @RequestParam String transactionCode, @RequestParam String orderId, HttpServletRequest request) {
//business logic
}

}

如果我点击这个链接,会出现405错误,即方法不允许。

起初,我发现请求被启用在Web应用程序上的CSFR过滤器所阻止了,因此我已经按照以下方式配置了我的安全性:

@Configuration
@ComponentScan("it.besmart")
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Autowired
    @Qualifier("customUserDetailsService")
    UserDetailsService userDetailsService;

    @Autowired
    CustomSuccessHandler customSuccessHandler;

    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    DataSource dataSource;

    private final static Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    @Autowired
    public void configureGlobalService(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SwitchUserFilter switchUserFilter() {
        SwitchUserFilter filter = new SwitchUserFilter();
        filter.setUserDetailsService(userDetailsService);
        filter.setSuccessHandler(customSuccessHandler);
        filter.setFailureHandler(customAuthenticationFailureHandler);
        return filter;
    }

        protected void configure(HttpSecurity http) throws Exception {
            logger.debug("Webapp security configured");


            http

            .authorizeRequests()
                    .antMatchers("/",  "/home", "/contacts", "/faq", "/privacy", "/register", "/registrationConfirm", "/util/**", "/resendRegistrationToken","/park**", "/oauth/authorize", "/error")
                    .permitAll()
                    .antMatchers("/profile**", "/edit**","/payment**", "/plate**","/notification**", "/addPaymentMethod**", "/logout/impersonate**")
                    .access("hasRole('USER') or hasRole('NOPAYMENT')")
                    .antMatchers("/book**", "/manage**")
                    .access("hasRole('USER')")
                    .antMatchers("/admin**", "/login/impersonate**").access("hasRole('ADMIN')")
                    .antMatchers("/updatePassword").hasAuthority("CHANGE_PASSWORD_PRIVILEGE")

                    .and().formLogin().loginPage("/?login=login").loginProcessingUrl("/")                   .successHandler(customSuccessHandler).failureHandler(customAuthenticationFailureHandler).usernameParameter("email").passwordParameter("password").and().rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400).and().exceptionHandling().accessDeniedPage("/accessDenied")

                    .and().csrf().ignoringAntMatchers( "/util**")
                    .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/?logout=true").permitAll()


                    .and().addFilterAfter(switchUserFilter(), FilterSecurityInterceptor.class);

        }

这样我就不会收到CSRF令牌异常,但仍然会收到405错误。 问题并不是POST,因为如果我将请求和映射更改为GET,我仍然会遇到405错误...如果我尝试发送POST请求,我可以在头部响应中看到允许使用的方法是POST,如果我以GET方式发送它,我会看到允许使用的方法是POST...很奇怪

我不知道该去哪里找答案...


为了避免与安全相关的问题,您可以尝试在application.properties中添加property management.security.enabled=false属性,并确认是否可以这样工作? - marco
什么都没改...问题还在那里... - MarioC
那看起来不像是一个安全问题...你如何发送POST请求?同时,尝试在所有的RequestParam中添加required=false,在应用程序调试时在控制器的第一行设置断点。 - marco
@RequestParam(value = "yourParamName", required = false) - marco
你是对的!有一个空参数!但是我收到了一个405错误,这很奇怪... - MarioC
4个回答

11

在我的情况下,端点启用了ssl,即为https

由于疏忽,在Postman中我错误地使用了http

http可以正常工作GET请求,但对于POST请求,则会返回405方法不允许。如果您的端点需要,则必须使用https

如果您在Spring中打开了请求和响应日志记录,则上述情况中的POST端点将按以下方式记录:

[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,915Z (UTC+0) [http-nio-80-exec-6] DEBUG o.s.w.f.CommonsRequestLoggingFilter - Before request [GET /api/v1/my-app, client=1.2.3.4, user=aUser]
[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,915Z (UTC+0) [http-nio-80-exec-6] WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,916Z (UTC+0) [http-nio-80-exec-6] DEBUG o.s.w.f.CommonsRequestLoggingFilter - After request [GET /api/v1/my-app, client=1.2.3.4, user=aUser]


这种情况发生在我身上,也许我们应该在文档中包含这个原因,你觉得呢? - Rigoberto Peña

5

所以问题是其中一个参数为空。通过在请求参数注释中添加required=null,已经解决了这个问题,就像这样:

@RequestParam(value = "yourParamName", required = false)

这会导致一个HTTP错误405,可以在这里找到定义:

6.5.5.  405 Method Not Allowed

The 405 (Method Not Allowed) status code indicates that the method
received in the request-line is known by the origin server but not
supported by the target resource.  The origin server MUST generate an
Allow header field in a 405 response containing a list of the target
resource's currently supported methods.

A 405 response is cacheable by default; i.e., unless otherwise
indicated by the method definition or explicit cache controls (see
Section 4.2.2 of [RFC7234]).

当“目标资源”在此处定义时:


1

还要记得检查协议。在我的情况下,它必须是https而不是http

错误消息当然可以更详细!


0
在我的情况下,我在控制器中以以下方式进行映射:
@RequestMapping(name = "/fetch", method = RequestMethod.POST)
public Long createFetch() throws IOException {
    return fetchService.doFetch();
}

如果你注意到了,上面的映射是针对 name 的,但请求却使用了这个。一旦我在 @Controller 和方法级别应用相同的操作,就开始看到了这个错误。将路径设置为 value 可以解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接