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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:27:12  来源:igfitidea点击:

Spring Security - 405 Request Method 'POST' Not Supported

javaspringspring-mvc

提问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 csrftoken in the form.

我已经在我的项目中实现了 Spring Security,但是当我尝试登录时我的状态是 405。我已经csrfform.

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 csrftoken, 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 csrfis 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 /loginwhich only takes a GETrequest. You could create another controller method to receive that POSTrequest 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-loginand the processing url is /loginthis means in your controller you need remove the mapping for /loginand 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 successForwardUrland 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

解决我的问题