我有一个Spring Web应用程序应该受到表单身份验证的保护(我出于某种原因无法使用Spring Security )。
如果我请求受保护的资源,我将被重定向到登录表单并输入凭据。凭据正确后,我将被重定向到requestet资源。一切都应该是这样。
但是当我输入错误的凭据时,我会收到HTTP 405
消息,而不是错误页面。的为什么吗
的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以某种方式“捕获”了请求。有可能避免这种情况吗?
答案 0 :(得分:0)
来自wiki:
405方法不允许:请求的资源不支持请求方法;例如,表单上的GET请求需要通过POST显示数据,或者在只读资源上显示PUT请求。
您所要做的就是将您的控制器RequestMethod
从GET
更改为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() {
...
}
}
根据您的图片:
您显然是在尝试将表单发布到此网址: / 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下提供错误页面-但不能。