使用错误凭据的表单身份验证会导致HTTP 405(方法不允许)

时间:2017-06-07 08:22:48

标签: java spring security authentication

我有一个Spring Web应用程序应该受到表单身份验证的保护(我出于某种原因无法使用Spring Security )。

如果我请求受保护的资源,我将被重定向到登录表单并输入凭据。凭据正确后,我将被重定向到requestet资源。一切都应该是这样。

See Network Screenshot

但是当我输入错误的凭据时,我会收到HTTP 405消息,而不是错误页面。的为什么吗

See Network Screenshot

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Authentication</web-resource-name>
            <url-pattern>/test/auth/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>users</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/loginerror.html</form-error-page>
        </form-login-config>
    </login-config>

    <security-role>
        <role-name>users</role-name>
    </security-role>

</web-app>

的login.html

<!DOCTYPE html>
<html>
<body>

<form method="post" action="j_security_check">
    <table>
        <tr>
            <td colspan="2">Please type in your user name and password</td>
        </tr>
        <tr>
            <td>Name:</td>
            <td><input type="text" name="j_username" width="40"/></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input type="password" name="j_password" /></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Login" /></td>
        </tr>
    </table>
</form>

</body>
</html>

为loginError.html

<!DOCTYPE html>
<html>
<body>

error!

</body>
</html>

日志

WARN [http-nio-8080-exec-79] o.s.web.servlet.PageNotFound: Request method 'POST' not supported

控制器

@RestController
@RequestMapping("/test")
public class TestController {

    private final static Logger LOG = LoggerFactory.getLogger(TestController.class);

    @Autowired
    private HttpServletRequest request;

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test() {
        printAuth();
        return "test";
    }

    @RequestMapping(value = "/auth/test", method = RequestMethod.GET)
    public String testAuth() {
        printAuth();
        return "testAuth";
    }

    @RequestMapping(value = "/auth/test2", method = RequestMethod.GET)
    public String testAuth2() {
        printAuth();
        return "testAuth2";
    }

    private void printAuth() {
        Principal principal = request.getUserPrincipal();
        LOG.debug("Request: " + request);
        LOG.debug("Principal: " + principal);
        LOG.debug("Principal name :" + principal.getName());
        LOG.debug("User in Role 'users': " + request.isUserInRole("users"));
    }

}

更新

我尝试使用spimple“non Spring”应用程序进行相同的身份验证,它运行正常。所以我假设Spring servlet以某种方式“捕获”了请求。有可能避免这种情况吗?

3 个答案:

答案 0 :(得分:0)

来自wiki:

  

405方法不允许:请求的资源不支持请求方法;例如,表单上的GET请求需要通过POST显示数据,或者在只读资源上显示PUT请求。

您所要做的就是将您的控制器RequestMethodGET更改为POST

您无法发布HTTP表单+尝试使用GET方法处理它。

类似的东西:

@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public String test() {
      ...
    }

    @RequestMapping(value = "/auth/test", method = RequestMethod.POST)
    public String testAuth() {
      ...
    }

    @RequestMapping(value = "/auth/test2", method = RequestMethod.POST)
    public String testAuth2() {
       ...
    }

}

根据您的图片:

enter image description here

您显然是在尝试将表单发布到此网址: / test / auth

根据您的控制器代码:

@RequestMapping(value = "/auth/test", method = RequestMethod.GET)
public String testAuth() {
    printAuth();
    return "testAuth";
}

您正在使用GET,这样做有误,请尝试将其更改为POST。

答案 1 :(得分:0)

就像我在更新中假设的那样,Spring servlet负责这个问题。因此,我必须确保另一个servlet服务于登录页面而不是Spring servlet。

<强>的web.xml

Union-Object

答案 2 :(得分:0)

我遇到了同样的问题,发现的所有信息都是,被调用的servlet没有实现doPost()方法。但是,嘿,那个j_security_check URL不是我创建的servlet,它是tomcat提供的servlet!?!?!?

错了!这是错误页面,必须具有doPost()方法

考虑一下,这很有意义。 用户打开任何受保护的页面。 Tomcat在请求的URL下提供登录表单。 用户输入了错误的用户/密码,数据被发布到j_security_check servlet中。由于凭据错误,它会在此URL下提供错误页面-但不能。