使用 Spring Security 登录:不支持请求方法“POST”

Posted

技术标签:

【中文标题】使用 Spring Security 登录:不支持请求方法“POST”【英文标题】:Login with Spring Security : Request method 'POST' not supported 【发布时间】:2015-07-07 14:00:29 【问题描述】:

我在使用 Spring Security 登录时遇到问题。登录页面显示正常,但每当我想实际登录时,都会出现以下错误:

Etat HTTP 405 - 不支持请求方法“POST”。

由于我使用的是 Spring Security 4.0.1,请注意表单操作中使用的 /login 引用了 Spring Security 的内置身份验证引擎。因此它与控制器中登录方法中的/login不同。

以下是相关文件:

login.jsp:

<body onload='document.loginForm.username.focus();'>

<h1>Spring Security Custom Login Form (Annotation)</h1>

<div id="login-box">

    <h2>Login with Username and Password</h2>

    <c:if test="$not empty error">
        <div class="error">$error</div>
    </c:if>
    <c:if test="$not empty msg">
        <div class="msg">$msg</div>
    </c:if>

    <form name='loginForm'
        action="<c:url value='/login' />" method='POST'>

        <table>
        <tr>
            <td>User:</td>
            <td><input type='text' name='username' value=''></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input type='password' name='password' /></td>
        </tr>
        <tr>
                <td colspan='2'>
                            <input name="submit" type="submit" value="submit" />
                            </td>
        </tr>
       </table>

       <input type="hidden" 
                 name="$_csrf.parameterName" value="$_csrf.token" />
    </form>
</div>

主控制器:

    @Controller
    public class MainController 
    
    private static final Logger logger = LoggerFactory.getLogger(MainController.class);
    
    @RequestMapping(value = "/login", method=RequestMethod.GET)
    public ModelAndView login(
            @RequestParam(value="erreur",required = false) String erreur,
            @RequestParam(value="logout",required = false) String logout) 
        ModelAndView model = new ModelAndView();
        if(erreur != null) 
            model.addObject("erreur", "Identifiants incorrectes");
        
        if(logout != null) 
            model.addObject("msg","you have been logged out successfully");
        
        return model;
    
    
    @RequestMapping(value = "/admin**", method = RequestMethod.GET)
    public String admin(Locale locale, Model model) 
        logger.info("Bienvenue ! vous êtes en .", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "admin";
    
    
    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public ModelAndView accesssDenied() 
 
      ModelAndView model = new ModelAndView();
 
      //verifier si l'utilisateur est connecté
      Authentication auth = SecurityContextHolder.getContext().getAuthentication();
      logger.info("Authentification:"+auth);
      if (!(auth instanceof AnonymousAuthenticationToken)) 
        UserDetails userDetail = (UserDetails) auth.getPrincipal(); 
        model.addObject("username", userDetail.getUsername());
      
 
      model.setViewName("403");
      return model;
 
    
    
    @RequestMapping(value = "/","/index", method = RequestMethod.GET)
    public String home(Locale locale, Model model) 
        logger.info("Bienvenue ! vous êtes en .", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "index";
    

spring-security.xml:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">
 
    <http auto-config="true" use-expressions="true">
        <access-denied-handler error-page="/403" />
        <intercept-url pattern="/admin**" access="hasRole('admin')" />
        <form-login 
            login-page="/login" 
            default-target-url="/index" 
            authentication-failure-url="/login?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" invalidate-session="true"/>
        <!--   enable csrf protection -->
        <csrf/> 
    </http>
    
 
    <authentication-manager>
      <authentication-provider>
        <jdbc-user-service data-source-ref="dataSource"
          users-by-username-query=
            "select login,pwd, enabled from utilisateur where login=?"
          authorities-by-username-query=
            "select login, role from role where login =?" />
      </authentication-provider>
    </authentication-manager>
</beans:beans>

【问题讨论】:

所有MainController处理方法都映射到method=RequestMethod.GET 【参考方案1】:

您正在对服务进行POST 调用,该服务公开为GET

@RequestMapping(value = "/login", method=RequestMethod.GET)


<form name='loginForm'
        action="<c:url value='/login' />" method='POST'>

这就是你收到这个的原因。

【讨论】:

我正在使用 Spring security 4,据我了解,它使用 url /login 而不是之前的 /j_security_login_check 和 POST 进行身份验证用户。这通常会给我以下结构: - /login 和 GET :调用控制器以显示登录页面。 -/login with POST : 调用 spring 安全认证机制。【参考方案2】:

我刚刚发现了问题所在,在登录 JSP 中我使用表达式语言来评估 csrf 参数名称和令牌,我只是忘记在登录页面中添加 &lt;%@ page isELIgnored="false"%&gt; 属性。

【讨论】:

以上是关于使用 Spring Security 登录:不支持请求方法“POST”的主要内容,如果未能解决你的问题,请参考以下文章

错误 405 请求方法 'POST' 不支持 Spring Security

如何配置 Spring Boot 和 Spring Security 以支持表单登录和 Google OAuth2 登录

spring security 不支持application/json 解决办法

spring-security 如何使用用户名或邮箱登录

Spring Security自定义登录认证与数据持久化

Spring security自定义登录页面不重定向