簡體   English   中英

Spring security登錄報錯“不支持請求方法‘POST’”

[英]Spring security login error "Request method 'POST' not supported"

我已經查看了我能找到的所有相關問題,但未能找到適用於我的場景的答案。 我使用的是 Spring WebSecurityConfigurerAdapter,我能夠驗證單個用戶類型,但是在配置我的 SecurityConfig 類來處理多個用戶類型之后,我收到了“不支持請求方法‘POST’”的錯誤,盡管我仍然formLogin().loginPage(URL...) 的相同 URL。

我有 4 個靜態類,順序為 1、2、3 和 4,盡管前 2 個只是為了允許未經身份驗證的用戶訪問具有模式/用於家庭和/account/*用於其他事物的 URL。 所有這些靜態類都正常工作,當訪問帶有模式/company/*/candidate/*的 URL 時,用戶將被定向到適當的登錄頁面進行登錄。

這就是現在出現問題的地方。 我在 formLogin().loginPage(arg) 中使用“/account/candidateLogin”和“/account/companyLogin”作為參數,但我之前使用的相同控制器方法不再正常工作。 我收到 405 錯誤並且控制台顯示osweb.servlet.PageNotFound: Request method 'POST' not supported

這是相關代碼,在此先感謝您:

安全配置.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers( "/images/**",
            "/vendor/**",
            "/app.css",
            "/app.js",
            "/favicon.png");
    }

    @Configuration
    @Order(1)
    public static class HomePageSecurityConfigurationAdapter extends 
    WebSecurityConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/")
                .authorizeRequests().anyRequest().permitAll();

       }
    }

    @Configuration
    @Order(2)
    public static class AccountSecurityConfigurationAdapter extends 
    WebSecurityConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/account/*")
                .authorizeRequests().anyRequest().permitAll();

        }
    }


    @Configuration
    @Order(3)
    public static class CompanySecurityConfigurationAdapter extends 
    WebSecurityConfigurerAdapter {

        @Autowired
        private CompanyService companyService;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(companyService);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/company/*")
                .authorizeRequests()
                .anyRequest()
                .hasRole("COMPANY")
                .and()
                .formLogin()
                .loginPage("/account/companyLogin")
                .successHandler(companyLoginSuccessHandler())
                .failureHandler(companyLoginFailureHandler())
                .and()
                .logout()
                .logoutSuccessUrl("/");
        }

        public AuthenticationSuccessHandler companyLoginSuccessHandler() {
            return (request, response, authentication) -> response.sendRedirect("/company/companyProfile");
        }

        public AuthenticationFailureHandler companyLoginFailureHandler() {
            return (request, response, exception) -> {
                request.getSession().setAttribute("flash", new FlashMessage("Incorrect username and/or password. Please try again.", FlashMessage.Status.FAILURE));
                response.sendRedirect("/account/companyLogin");
            };
        }
    }

    @Configuration
    @Order(4)
    public static class CandidateSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Autowired
        private CandidateService candidateService;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(candidateService);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/candidate/*")
                .authorizeRequests()
                .anyRequest()
                .hasRole("CANDIDATE")
                .and()
                .formLogin()
                .loginPage("/account/candidateLogin")
                .successHandler(candidateLoginSuccessHandler())
                .failureHandler(candidateLoginFailureHandler())
                .and()
                .logout()
                .logoutSuccessUrl("/");
        }

        public AuthenticationSuccessHandler candidateLoginSuccessHandler() {
            return (request, response, authentication) -> response.sendRedirect("/candidate/candidateProfile");
        }

        public AuthenticationFailureHandler candidateLoginFailureHandler() {
            return (request, response, exception) -> {
                request.getSession().setAttribute("flash", new FlashMessage("Incorrect username and/or password. Please try again.", FlashMessage.Status.FAILURE));
                response.sendRedirect("/account/candidateLogin");
            };
        }
    }
}

登錄 URI 的控制器。 這些都是一樣的,只是一個用於候選人登錄,一個用於公司

@Controller()
public class AccountController {

    @Autowired
    private CandidateService candidateService;

    @Autowired
    private CompanyService companyService;

    @RequestMapping(value = "/account/candidateLogin", method = RequestMethod.GET)
    public String candidateLoginForm(Model model, HttpServletRequest request) {
        model.addAttribute("candidate", new Candidate());
        try {
            Object flash = request.getSession().getAttribute("flash");
            model.addAttribute("flash", flash);
            model.addAttribute("action", "/account/candidateLogin");
            model.addAttribute("submit","Login");

            request.getSession().removeAttribute("flash");
        } catch (Exception e) {
            //Flash session attribute must not exist. Do nothing and proceed.
        }
        return "account/candidateLogin";
    }

    @RequestMapping(value = "/account/companyLogin", method = RequestMethod.GET)
    public String loginCompanyForm(Model model, HttpServletRequest request) {
        model.addAttribute("company", new Company());
        try {
            Object flash = request.getSession().getAttribute("flash");
            model.addAttribute("flash", flash);
            model.addAttribute("action", "/account/companyLogin");
            model.addAttribute("submit","Login");

            request.getSession().removeAttribute("flash");
        }  catch (Exception e) {
            //Flash session attribute must not exist. Do nothing and proceed.
        }
        return "account/companyLogin";
    }

登錄 HTML 文件。 我只包括一個,因為唯一的區別是變量名。

<!DOCTYPE html>
<html lang="en">
<head th:replace="layout :: head('explore')"></head>
<body>
<div th:replace="layout :: nav"></div>
<div th:replace="layout :: login"></div>


<h1 style="margin-left: 25%">Company Login</h1>
<div class="grayContainer">
    <div th:fragment="login">
        <div class="row">
            <div class="col s12">
                <div th:replace="layout :: flash"></div>
                <form th:action="@{${action}}" th:object="${company}" method="post">
                    <div class="input-field" style="width: 70%; margin: 0 auto;">
                        <input type="text" th:field="*{username}" placeholder="Username/Email"/>
                    </div>
                    <div class="input-field" style="width: 70%; margin: 0 auto;">
                        <input type="password" th:field="*{password}" placeholder="Password"/>
                    </div>
                    <button class="button" type="${submit}" style="text-align: center;">Login</button>Forgot password?
                </form>
            </div>
        </div>
    </div>
</div>

<div th:replace="layout :: scripts"></div>

</body>

編輯

正如一些人所建議的那樣,我將登錄表單的請求映射中的方法更改為 POST 而不是 GET 並啟用了安全日志記錄。 現在我根本無法訪問登錄頁面,它給我一個 405 錯誤,這是安全調試器日志:

************************************************************


2018-03-06 14:27:48.820  INFO 4495 --- [nio-8080-exec-4] Spring Security Debugger                 : 

************************************************************

Request received for GET '/account/candidateLogin':

org.apache.catalina.connector.RequestFacade@4cf3f981

servletPath:/account/candidateLogin
pathInfo:null
headers: 
host: localhost:8080
connection: keep-alive
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
referer: http://localhost:8080/account/selectType
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cookie: JSESSIONID=58FD34AB4F9796EC523C355C0A51ED49


Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  CsrfFilter
  LogoutFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]


************************************************************


2018-03-06 14:27:48.829  WARN 4495 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound             : Request method 'GET' not supported

對於請求映射

@RequestMapping(value = "/account/candidateLogin", method = RequestMethod.GET)

@RequestMapping(value = "/account/companyLogin", method = RequestMethod.GET)

它們以您的形式映射到請求的 GET 方法

<form th:action="@{${action}}" th:object="${company}" method="post">

它的帖子。

您可以嘗試從您的表單中傳遞 CSRF 令牌嗎?

<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />

在你的java代碼中,請求方法是GET,

@RequestMapping(value = "/account/companyLogin", method = RequestMethod.GET)

而在你的 html 代碼中,請求方法是 POST,

<form th:action="@{${action}}" th:object="${company}" method="post">

你應該讓他們保持不變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM