java Spring Security - 不支持 405 请求方法“POST”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42206998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security - 405 Request Method 'POST' Not Supported
提问by Eniss
I have implemented Spring Security to my project, but I am getting status 405 when I try to log in. I have already added csrf
token in the form
.
我已经在我的项目中实现了 Spring Security,但是当我尝试登录时我的状态是 405。我已经csrf
在form
.
This is the error I am getting when I send username and password:
HTTP Status 405 - Request method 'POST' not supported
这是我发送用户名和密码时遇到的错误:
HTTP Status 405 - Request method 'POST' not supported
Spring version: 4.0.2.RELEASED
Spring 版本:4.0.2.RELEASED
<div class="login-form">
<c:url var="loginUrl" value="/login" />
<form action="${loginUrl}" method="post" class="form-horizontal">
<c:if test="${param.error != null}">
<div class="alert alert-danger">
<p>Invalid username and password.</p>
</div>
</c:if>
<c:if test="${param.logout != null}">
<div class="alert alert-success">
<p>You have been logged out successfully.</p>
</div>
</c:if>
<div class="input-group input-sm">
<label class="input-group-addon" for="username">
<i class="fa fa-user"></i>
</label>
<input type="text" class="form-control" id="username"
name="clientusername" placeholder="Enter Username" required>
</div>
<div class="input-group input-sm">
<label class="input-group-addon" for="password">
<i class="fa fa-lock"></i>
</label>
<input type="password" class="form-control" id="password"
name="clientpassword" placeholder="Enter Password" required>
</div>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<div class="form-actions">
<input type="submit" class="btn btn-block btn-primary btn-default"
value="Log in">
</div>
</form>
</div>
Security Configuration:
安全配置:
@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();
}
Controller:
控制器:
@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;
}
Almost every topic about this issue says that we need to add csrf
token, but I already added. Am I missing something?
几乎每个关于这个问题的话题都说我们需要添加csrf
令牌,但我已经添加了。我错过了什么吗?
采纳答案by Alican Balik
You can set two endpoints for one url. But you cannot set any request parameter as required. As I saw your request map for login, you can set your request method like this:
您可以为一个 url 设置两个端点。但是您不能根据需要设置任何请求参数。当我看到您的登录请求映射时,您可以像这样设置请求方法:
@RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView loginPage() {
return new ModelAndView("login");
}
回答by px06
First of all csrf
is enabled by defaultin Spring as of Spring 4.0 so there no need to explicitly enable it yourself.
首先,csrf
在默认情况下启用在Spring作为春季4.0的所以没有必要给自己明确启用它。
Secondly, there is no endpoint for you to authenticate your login. What you're doing is sending a request to /login
which only takes a GET
request. You could create another controller method to receive that POST
request and authenticate or you could use a UserDetailsService
.
其次,您没有端点可以验证您的登录信息。你正在做的是发送一个/login
只接受一个GET
请求的请求。您可以创建另一个控制器方法来接收该POST
请求并进行身份验证,或者您可以使用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);
}
Here our view page is /user-login
and the processing url is /login
this means in your controller you need remove the mapping for /login
and add the following:
这是我们的视图页面/user-login
和处理 url/login
这意味着在您的控制器中您需要删除映射/login
并添加以下内容:
Controller
控制器
@RequestMapping(value="/user-login", method=RequestMethod.GET)
public ModelAndView loginForm() {
return new ModelAndView("login-form");
}
And change your view.
并改变你的看法。
View (login-form.jsp)
查看(登录表单.jsp)
<c:url value="/login" var="loginUrl"/>
<form action="${loginUrl}" method="post" modelAttribute="user">
Username: <input type="text" id="username" name="username" placeholder=""><br>
Password: <input type="password" id="password" name="password" placeholder=""><br>
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}"/>
<button type="submit">Login</button>
</form>
回答by davemilligan
I started getting the same thing when I added a successForwardUrl
and found that the response on sucessful login is a POST to that endpoint or to "/" if not set. Once I enabled POST on the defined endpoint as well as GET all was fine.
当我添加 asuccessForwardUrl
并发现成功登录的响应是对该端点的 POST 或“/”(如果未设置)时,我开始得到相同的结果。一旦我在定义的端点上启用 POST 以及 GET 一切都很好。
回答by lane.maxwell
You are calling for a POST yet have only defined GET methods. Change your endpoint to RequestMethod.POST
您正在调用 POST 但只定义了 GET 方法。将您的端点更改为 RequestMethod.POST
回答by arun kumar rout
Check your web.xml file you might forgot to keep "securityFilterChain"
检查您的 web.xml 文件,您可能忘记保留“securityFilterChain”
Use this code in web.xml file
在 web.xml 文件中使用此代码
<!-- Security configuration goes here -->
<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>
回答by Phat Le
If you are using JSP/JSTL
如果您使用的是 JSP/JSTL
Change
改变
<form action="${loginUrl}" method="post"></form>
to
到
<form:form action="${loginUrl}" method="post" </form:form>
with tag declaration
带标签声明
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
solve my problem
解决我的问题