[英]Spring Security - 405 Request Method 'POST' Not Supported
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。我已经在
form
中添加了csrf
令牌。
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春季版: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.几乎每个关于这个问题的话题都说我们需要添加
csrf
令牌,但我已经添加了。 Am I missing something?我错过了什么吗?
First of all csrf
is enabled by default in Spring as of Spring 4.0 so there no need to explicitly enable it yourself.首先,从 Spring 4.0 开始,Spring 中默认启用
csrf
,因此无需自己显式启用它。
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.你正在做的是向
/login
发送一个请求,它只接受一个GET
请求。 You could create another controller method to receive that POST
request and authenticate or you could use a UserDetailsService
.您可以创建另一个控制器方法来接收该
POST
请求并进行身份验证,或者您可以使用UserDetailsService
。
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
的映射并添加以下内容:
@RequestMapping(value="/user-login", method=RequestMethod.GET)
public ModelAndView loginForm() {
return new ModelAndView("login-form");
}
And change your view.并改变你的看法。
<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>
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.当我添加一个
successForwardUrl
并发现成功登录时的响应是对该端点的 POST 或“/”(如果未设置)时,我开始得到同样的结果。 Once I enabled POST on the defined endpoint as well as GET all was fine.一旦我在定义的端点上启用 POST 以及 GET 一切都很好。
Check your web.xml file you might forgot to keep "securityFilterChain"检查您可能忘记保留“securityFilterChain”的 web.xml 文件
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>
You are calling for a POST yet have only defined GET methods.您正在调用 POST 但只定义了 GET 方法。 Change your endpoint to RequestMethod.POST
将您的端点更改为 RequestMethod.POST
You can set two endpoints for one url.您可以为一个 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:
当我看到您的登录请求映射时,您可以像这样设置请求方法:
@RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView loginPage() {
return new ModelAndView("login");
}
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解决我的问题
Ensure that the Spring Security filter chain is registered.确保 Spring Security 过滤器链已注册。
With Java configuration, this can be done by creating a class that extends AbstractSecurityWebApplicationInitializer
.使用 Java 配置,这可以通过创建一个扩展
AbstractSecurityWebApplicationInitializer
的类来完成。
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {
}
Alternatively, edit web.xml and add the following code.或者,编辑 web.xml 并添加以下代码。 (See the documentation .)
(请参阅文档。)
<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.