Spring Security – 405请求方法’POST’不受支持

我已经为我的项目实现了Spring Security,但是当我尝试登录时,我获得状态csrf我已经在form添加了csrf令牌。

这是我发送用户名和密码时出现的错误: HTTP Status 405 - Request method 'POST' not supported

春季版:4.0.2.RELEASED

  

安全配置:

 @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("G2BUserDetailsService") UserDetailsService userDetailsService; @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/home").permitAll() .antMatchers("/admin/**").access("hasRole('ADMIN')") .and().formLogin().loginPage("/login") .usernameParameter("clientusername").passwordParameter("clientpassword") .and().csrf() .and().exceptionHandling().accessDeniedPage("/Access_Denied"); // .and().csrf().disable(); } 

控制器:

 @RequestMapping(value = "/login", method = RequestMethod.GET) public ModelAndView loginPage() { return new ModelAndView("login"); } @RequestMapping(value="/logout", method = RequestMethod.GET) public String logoutPage (HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null){ new SecurityContextLogoutHandler().logout(request, response, auth); } return "redirect:/login?logout"; } @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET) public ModelAndView accessDeniedPage(ModelMap model) { model.addAttribute("user", getPrincipal()); return new ModelAndView("accessDenied"); } @RequestMapping(value = "/admin", method = RequestMethod.GET) public ModelAndView adminPage(ModelMap model) { model.addAttribute("user", getPrincipal()); return new ModelAndView("admin"); } private String getPrincipal(){ String userName = null; Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { userName = ((UserDetails)principal).getUsername(); } else { userName = principal.toString(); } return userName; } 

几乎关于这个问题的每个主题都说我们需要添加csrf令牌,但我已经添加了。 我错过了什么吗?

您可以为一个URL设置两个端点。 但是您无法根据需要设置任何请求参数。 当我看到您的登录请求地图时,您可以设置您的请求方法,如下所示:

 @RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST }) public ModelAndView loginPage() { return new ModelAndView("login"); } 

首先,从Spring 4.0开始,默认情况下会启用 csrf ,因此无需自己明确启用它。

其次,您没有端点可以validation您的登录信息。 你正在做的是向/login发送一个只接受GET请求的请求。 您可以创建另一个控制器方法来接收该POST请求并进行身份validation,或者您可以使用UserDetailsService

SecurityConfiguration

 protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login-form") .anonymous() .and() .formLogin() .loginPage("/user-login") .defaultSuccessUrl("/admin", true) // the second parameter is for enforcing this url always .loginProcessingUrl("/login") .failureUrl("/user-login") .permitAll(); } @Autowired private UserDetailsService userDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder pe = new BCryptPasswordEncoder(); auth.userDetailsService(userDetailsService).passwordEncoder(pe); } 

这里我们的视图页面是/user-login ,处理URL是/login这意味着在你的控制器中你需要删除/login的映射并添加以下内容:

调节器

 @RequestMapping(value="/user-login", method=RequestMethod.GET) public ModelAndView loginForm() { return new ModelAndView("login-form"); } 

并改变你的观点。

查看(login-form.jsp)

  
Username:
Password:

您正在调用POST但只定义了GET方法。 将您的端点更改为RequestMethod.POST

当我添加successForwardUrl时,我开始得到相同的东西,并发现成功登录的响应是对该端点的POST或如果未设置则为“/”。 一旦我在定义的端点上启用了POST以及GET,一切都很好。