首页 文章

HTTP状态405 - 不支持请求方法'POST' - Spring Security

提问于
浏览
2

当我尝试实现Spring安全性时,我收到以下错误 -

控制器:

@Controller
public class EmployeeController {

    @RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
    public ModelAndView defaultPage() {

        ModelAndView model = new ModelAndView();
        model.addObject("title", "Spring Security + Hibernate Example");
        model.addObject("message", "This is default page!");
        model.setViewName("hello");
        return model;
    }

    @RequestMapping(value = "/admin**", method = RequestMethod.GET)
    public ModelAndView adminPage() {

        ModelAndView model = new ModelAndView();
        model.addObject("title", "Spring Security + Hibernate Example");
        model.addObject("message", "This page is for ROLE_ADMIN only!");
        model.setViewName("admin");

        return model;
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "logout", required = false) String logout,
            HttpServletRequest request) {

        ModelAndView model = new ModelAndView();
        if (error != null) {
            model.addObject("error",
                    getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
        }

        if (logout != null) {
            model.addObject("msg", "You've been logged out successfully.");
        }
        model.setViewName("login");

        return model;
    }

    // customize the error message
    private String getErrorMessage(HttpServletRequest request, String key) {

        Exception exception = (Exception) request.getSession()
                .getAttribute(key);

        String error = "";
        if (exception instanceof BadCredentialsException) {
            error = "Invalid username and password!";
        } else if (exception instanceof LockedException) {
            error = exception.getMessage();
        } else {
            error = "Invalid username and password!";
        }
        return error;
    }

    // for 403 access denied page
    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public ModelAndView accesssDenied() {

        ModelAndView model = new ModelAndView();

        // check if user is login
        Authentication auth = SecurityContextHolder.getContext()
                .getAuthentication();
        if (!(auth instanceof AnonymousAuthenticationToken)) {
            UserDetails userDetail = (UserDetails) auth.getPrincipal();
            System.out.println(userDetail);

            model.addObject("username", userDetail.getUsername());
        }

        model.setViewName("403");
        return model;
    }
}

web.xml中

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/mvc-dispatcher-servlet.xml,
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>
    <!-- /WEB-INF/spring-security.xml -->

    <!-- Spring Security -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

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-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />

        <!-- access denied page -->
        <access-denied-handler error-page="/403" />
        <form-login 
            login-page="/login" 
            default-target-url="/welcome"
            authentication-failure-url="/login?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" />
        <!-- enable csrf protection -->
        <csrf />
    </http>

    <authentication-manager>
        <authentication-provider user-service-ref="myUserDetailsService" >
            <password-encoder hash="bcrypt" />    
        </authentication-provider>
    </authentication-manager>

</beans:beans>

login.jsp的

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

    <h1>Spring Security Login Form (Database + Hibernate Authentication)</h1>

    <div id="login-box">

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

        <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='/j_spring_security_check' />" method='POST'>

            <table>
                <tr>
                    <td>User:</td>
                    <td><input type='text' name='username'></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>

</body>

错误:-

http://localhost:8080/EmployeeManagement/j_spring_security_check

09:01:22.135 [http-8080-4] DEBUG ossweb.DefaultRedirectStrategy - 重定向到'http:// localhost:8080 / EmployeeManagement / login; jsessionid = E27C22793BAA2C7FC38039260EC08152'09:01:22.135 [http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中 . 09:01:22.136 [http-8080-4] DEBUG osswcSecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成09:01:22.145 [http-8080-4] DEBUG ossecurity.web.FilterChainProxy - /登录位置1 11在额外的过滤链中;触发过滤器:'SecurityContextPersistenceFilter'09:01:22.145 [http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - HttpSession为SPRING_SECURITY_CONTEXT 09:01:22.145返回了空对象[http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - 没有可用的SecurityContext HttpSession:org.apache.catalina.session.StandardSessionFacade@48842f5e . 将创建一个新的 . 09:01:22.145 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤链中登录位置2的11;触发过滤器:'CsrfFilter'09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤器链中登录位置3的11;触发过滤器:'LogoutFilter'09:01:22.146 [http-8080-4] DEBUG osswumAntPathRequestMatcher - 请求'GET / login'与'POST / j_spring_security_logout 09:01:22.146 [http-8080-4] DEBUG os不匹配security.web.FilterChainProxy - /登录位于第4位的11位于额外的过滤链中;触发过滤器:'UsernamePasswordAuthenticationFilter'09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在另一个过滤器链中的第5位的登录;触发过滤器:'BasicAuthenticationFilter'09:01:22.146 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /登录位于第6位的11位于额外的过滤链中;触发过滤器:'RequestCacheAwareFilter'09:01:22.146 [http-8080-4] DEBUG osswsDefaultSavedRequest - pathInfo:both null(property equals)09:01:22.147 [http-8080-4] DEBUG osswsDefaultSavedRequest - queryString:both null ( property 等于)09:01:22.147 [http-8080-4] DEBUG osswsDefaultSavedRequest - requestURI:arg1 = / EmployeeManagement / admin; arg2 = / EmployeeManagement / login; jsessionid = E27C22793BAA2C7FC38039260EC08152(属性不等于)09:01:22.147 [http-8080-4] DEBUG osswsHttpSessionRequestCache - 保存的请求不匹配09:01:22.147 [http-8080-4] DEBUG ossecurity.web.FilterChainProxy - /在另一个过滤链中登录第7位的第11位;触发过滤器:'SecurityContextHolderAwareRequestFilter'09:01:22.147 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /登录位于第8位的11位于额外的过滤链中;触发过滤器:'AnonymousAuthenticationFilter'09:01:22.147 [http-8080-4] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - 带有匿名标记的填充SecurityContextHolder:'org.springframework.security.authentication.AnonymousAuthenticationToken@6fa90ed4:Principal:anonymousUser;证书:[受保护];认证:真实;详细信息:org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c:RemoteIpAddress:0:0:0:0:0:0:0:1; SessionId:E27C22793BAA2C7FC38039260EC08152;授权机构:ROLE_ANONYMOUS'09:01:22.147 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第9位的11位登录其他过滤链;触发过滤器:'SessionManagementFilter'09:01:22.148 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第10位的11位登录附加过滤链;触发过滤器:'ExceptionTranslationFilter'09:01:22.148 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - /在第11位的11位登录附加过滤链;触发过滤器:'FilterSecurityInterceptor'09:01:22.148 [http-8080-4] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - 检查请求匹配:'/ login';反对'/ admin **'09:01:22.148 [http-8080-4] DEBUG osswaiFilterSecurityInterceptor - 公共对象 - 未尝试认证09:01:22.148 [http-8080-4] DEBUG ossecurity.web.FilterChainProxy - /登录到达附加过滤链的末尾;继续使用原始链09:01:22.148 [http-8080-4] DEBUG osweb.servlet.DispatcherServlet - 名为'mvc-dispatcher'的DispatcherServlet处理[/ EmployeeManagement / login] 09:01:22.149的GET请求[http 8080-4] DEBUG oswsmaDefaultAnnotationHandlerMapping - 使用处理程序[com.employeemgmt.controller.EmployeeController@18ba5047]和1拦截器09:01:22.150 [http -8080-4] DEBUG osweb.servlet.DispatcherServlet将[/ login]映射到HandlerExecutionChain - Last-Modified值[/ EmployeeManagement / login]是: - 09:01:22.189 [http-8080-4] DEBUG oswbasHandlerMethodInvoker - 调用请求处理程序方法:public org.springframework.web.servlet.ModelAndView com.employeemgmt.controller.EmployeeController.login (java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest)09:01:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 在名为'login'09的bean上调用afterPropertiesSet(): 01:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 返回单例bean的缓存实例'org.springframework.transaction.config.internalTransactionAdvisor'09:01:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 返回缓存的实例of singleton bean'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'09:01:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 返回单例bean的缓存实例'org.springframework.transaction.config.internalTransactionAdvisor'09 :0 1:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 返回单例bean的缓存实例'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'09:01:22.190 [http-8080-4] DEBUG osweb.servlet .DispatcherServlet - 渲染视图[org.springframework.web.servlet.view.JstlView:name'login'; DispatcherServlet中的URL [/WEB-INF/pages/login.jsp]],名称为“mvc-dispatcher”09:01:22.190 [http-8080-4] DEBUG osbfsDefaultListableBeanFactory - 返回单例bean的缓存实例'requestDataValueProcessor'09: 01:22.190 [http-8080-4] DEBUG osweb.servlet.view.JstlView - 在InternalResourceView'login'09:01:22.279中转发资源[/WEB-INF/pages/login.jsp] [http-8080- 4] DEBUG osswcHttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中 . 09:01:22.279 [http-8080-4] DEBUG osweb.servlet.DispatcherServlet - 已成功完成请求09:01:22.279 [http-8080-4] DEBUG osswaExceptionTranslationFilter - 链正常处理09:01:22.280 [http 8080-4] DEBUG osswcSecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理已完成09:01:23.967 [http-8080-4] DEBUG ossecurity.web.FilterChainProxy - / j_spring_security_check位于第1位,共11个附加过滤链;触发过滤器:'SecurityContextPersistenceFilter'09:01:23.967 [http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - HttpSession为SPRING_SECURITY_CONTEXT 09:01:23.968返回了空对象[http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - 没有可用的SecurityContext HttpSession:org.apache.catalina.session.StandardSessionFacade@48842f5e . 将创建一个新的 . 09:01:23.968 [http-8080-4] DEBUG o.s.security.web.FilterChainProxy - / j_spring_security_check位于第2位的11位额外的过滤链;触发过滤器:'CsrfFilter'09:01:23.969 [http-8080-4] DEBUG ossecurity.web.csrf.CsrfFilter - 为http:// localhost:8080 / EmployeeManagement / j_spring_security_check 09:01:23.971找到无效的CSRF令牌http-8080-4] DEBUG osweb.servlet.DispatcherServlet - 名为'mvc-dispatcher'的DispatcherServlet处理[/ EmployeeManagement / 403]的POST请求09:01:23.971 [http-8080-4] DEBUG oswsmaDefaultAnnotationHandlerMapping - Mapping [ / 403] HandlerExecutionChain with handler [com.employeemgmt.controller.EmployeeController@18ba5047] and 1 interceptor 09:01:23.982 [http-8080-4] DEBUG oswsmaAnnotationMethodHandlerExceptionResolver - 解析来自handler [com.employeemgmt.controller.EmployeeController @的异常] 18ba5047]:org.springframework.web.HttpRequestMethodNotSupportedException:不支持请求方法'POST '09:01:23.984 [http-8080-4] DEBUG oswsmaResponseStatusExceptionResolver - 解决处理程序中的异常[com.employeemgmt.controller.EmployeeContr oller @ 18ba5047]:org.springframework.web.HttpRequestMethodNotSupportedException:不支持请求方法'POST '09:01:23.984 [http-8080-4] DEBUG oswsmsDefaultHandlerExceptionResolver - 解决处理程序中的异常[com.employeemgmt.controller.EmployeeController@18ba5047 ]:org.springframework.web.HttpRequestMethodNotSupportedException:请求方法'POST'不支持09:01:23.984 [http-8080-4] WARN osweb.servlet.PageNotFound - 请求方法'POST'不支持09:01:23.984 [ http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中 . 09:01:23.984 [http-8080-4] DEBUG osweb.servlet.DispatcherServlet - Null ModelAndView返回DispatcherServlet,名称为'mvc-dispatcher':假设HandlerAdapter完成请求处理09:01:23.984 [http-8080-4] DEBUG osweb.servlet.DispatcherServlet - 已成功完成请求09:01:23.984 [http-8080-4] DEBUG osswcHttpSessionSecurityContextRepository - SecurityContext为空或内容是匿名的 - 上下文不会存储在HttpSession中 . 09:01:23.984 [http-8080-4] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成

3 回答

  • 0

    您的控制器方法使用RequestMethod.GET注释,而login.jsp表单方法请求POST . 两者都应该是POST .

  • 0

    您正在控制器中的 /login 映射上使用 GET 方法 .

    使用POST方法进行身份验证是标准配置 .

    @RequestMapping(value = "/login", method = RequestMethod.GET) 更改为 @RequestMapping(value = "/login", method = RequestMethod.POST)

  • 0

    我在这里添加了OP找到的答案 .

    csrf标记值未被替换 . 一旦我添加 - <%@ page isELIgnored =“false”%>

    Personnaly我通过在spring-security中删除csrf来解决这个问题 . 在 http 标签集 <csrf disabled="true"/>

相关问题