我正在讨论这个问题......我有一个带有S2S通信的Spring Boot应用程序。我有一个@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,我在标题响应中看到Allowed方法是POST,如果我在GET中发送它,我会看到允许的方法POST ...很奇怪
我不知道在哪里看到......
答案 0 :(得分:1)
所以问题是其中一个参数为null。 已经解决了在请求参数注释中添加required = null的问题,如:
@RequestParam(value = "yourParamName", required = false)
这导致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]).
定义“目标资源”时here:
答案 1 :(得分:1)
在我的情况下,端点有 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]
答案 2 :(得分:0)
在我的情况下,我通过以下方式在控制器中进行了映射:
@RequestMapping(name = "/fetch", method = RequestMethod.POST)
public Long createFetch() throws IOException {
return fetchService.doFetch();
}
如果您注意到,上面的映射是到name
的,但是请求与此兼容。一旦在@Controller
级别和方法级别应用了相同的代码,便开始看到此错误。将路径设置为value
可以解决此问题。
答案 3 :(得分:0)
还要记得检查协议。就我而言,它必须是 https
而不是 http
错误信息当然可以更具描述性!