spring-boot表单登录/注销无法正常工作(找不到路径)

Aar*_*ski 5 java spring-mvc spring-security thymeleaf spring-boot

我有以下弹簧启动设置与表单登录和基本身份验证(部分工作 - 我可以登录到基本身份验证确定,登录表单出现).我只创建了登录表单,因为除非我这样做,否则我甚至无法获得登录.

注意:如果有帮助,在此填写代码:https://github.com/azeckoski/lti_starter

这是我的应用程序配置(相关部分)

@Order(23) // MED
@Configuration
public static class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/form").authorizeRequests().anyRequest().authenticated()
                .and().formLogin().permitAll().loginPage("/form/login").loginProcessingUrl("/form/login")
                .and().logout().logoutUrl("/form/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
    }
}

@Order(45) // LOW
@Configuration
public static class BasicAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/basic").authorizeRequests().anyRequest().authenticated()
            .and().httpBasic();
    }
}
Run Code Online (Sandbox Code Playgroud)

和表单登录控制器:

@Controller
@RequestMapping("/form")
public class FormController extends BaseController {

    @RequestMapping({"", "/"})
    public String home(HttpServletRequest req, Principal principal, Model model) {
        commonModelPopulate(req, principal, model);
        model.addAttribute("name", "form");
        model.addAttribute("canLogout", true);
        req.getSession().setAttribute("login", "form");
        return "home"; // name of the template
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(HttpServletRequest req) {
        log.info("login: " + req);
        return "login";
    }

    // Login form with error
    @RequestMapping(value = "/login", params = "error=true")
    public String loginError(HttpServletRequest req, Model model) {
        log.info("login-error: " + req);
        model.addAttribute("loginError", true);
        return "login";
    }
}
Run Code Online (Sandbox Code Playgroud)

我在百万富翁的登录表格:

<form th:action="@{/form/login}" method="post">
    <label for="username">Username</label>:
    <input type="text" id="username" name="username"/> <br/>
    <label for="password">Password</label>:
    <input type="password" id="password" name="password"/> <br/>
    <input type="submit" value="Login"/>
</form>
Run Code Online (Sandbox Code Playgroud)

我在百里香的登出表格:

<div sec:authorize="isAuthenticated()">
    <form th:if="${canLogout}" th:action="@{/form/logout}" method="post">
        <input type="submit" value="Logout"/>
    </form>
    <div>User: <span sec:authentication="name">AZ</span></div>
    <div>Roles: <span sec:authentication="principal.authorities">[ROLE_USER, ROLE_ADMIN]</span></div>
    <div>Login: <span th:text="${session.login}"/></div>
</div>
Run Code Online (Sandbox Code Playgroud)

但是,登录(和注销)不起作用.

当我尝试访问登录处理路径(提交登录表单)时,我在日志中遇到以下错误(使用logging.level.org.springframework.security = DEBUG):

2014-07-14 11:10:41.635 DEBUG 30608 --- [qtp502953897-14] ossweb.util.matcher.OrRequestMatcher:未找到匹配项2014-07-14 11:10:41.635 DEBUG 30608 --- [qtp502953897-14 ] ossecurity.web.FilterChainProxy:/ form/login没有匹配的过滤器

并在屏幕上:

出现意外错误(type = Bad Request,status = 400).实际请求参数未满足参数条件"error = true":password = {admin},username = {admin}

当我尝试访问注销处理路径(发布到/ form/logout)时,我在日志中遇到以下错误(使用logging.level.org.springframework.security = DEBUG):

2014-07-14 11:13:21.731 DEBUG 30778 --- [qtp865931040-14] ossweb.util.matcher.OrRequestMatcher:未找到匹配项2014-07-14 11:13:21.731 DEBUG 30778 --- [qtp865931040-14 ] ossecurity.web.FilterChainProxy:/ form/logout没有匹配的过滤器2014-07-14 11:13:21.738 WARN 30778 --- [qtp865931040-14] osweb.servlet.PageNotFound:不支持请求方法'POST'

并在屏幕上:

出现意外错误(type = Method Not Allowed,status = 405).请求方法"POST"不受支持

从所有文档和示例中我都可以发现它应该可行.这可能是因为我试图管理多种类型的身份验证方法,但我认为这是一个相当常见的用例.我尝试了大量没有进展的变种,所以我对任何想法或建议持开放态度.

我误会了吗?不应该在/ form/login和/ form/logout为我创建一个默认的登录和注销处理器吗?

Aar*_*ski 2

解决方案示例

这是一个示例,展示了应该如何完成它(包括 NoAuthConfigurationAdapter ,它将允许在 /form 路径之外访问安全信息。顺序很重要。

@Order(23) // MED
@Configuration
public static class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/form/**").authorizeRequests().anyRequest().authenticated()
                .and().formLogin().permitAll().loginPage("/form/login").loginProcessingUrl("/form/login")
                .and().logout().logoutUrl("/form/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
    }
}

@Order(67) // LOWEST
@Configuration
public static class NoAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // this ensures security context info (Principal, sec:authorize, etc.) is accessible on all paths
        http.antMatcher("/**").authorizeRequests().anyRequest().permitAll();
    }
}
Run Code Online (Sandbox Code Playgroud)