Spring安全登录失败错误重定向且无错误消息

Spring安全登录失败错误重定向且无错误消息,spring,spring-security,Spring,Spring Security,我正在尝试构建一个简单的登录表单(JS)并使用Spring安全性。据我所知,当登录失败时,它应该重定向到登录页面(或者只针对bootstrap项目内的JSP登录页面?),但它无法做到这一点。 查询错误字符串参数也为空 我的spring安全配置: @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configu

我正在尝试构建一个简单的登录表单(JS)并使用Spring安全性。据我所知,当登录失败时,它应该重定向到登录页面(或者只针对bootstrap项目内的JSP登录页面?),但它无法做到这一点。 查询错误字符串参数也为空

我的spring安全配置:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
                .and()
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .defaultSuccessUrl("/", true)
                .permitAll()
                .and()
            .httpBasic()
                .and()
            .csrf().disable()
            .logout()
                .permitAll()
                .logoutSuccessUrl("/");
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        // ensure the passwords are encoded properly
        User.UserBuilder users = User.withDefaultPasswordEncoder();
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(users.username("user").password("user").roles("USER").build());
        manager.createUser(users.username("admin").password("admin").roles("USER","ADMIN").build());
        return manager;
    }
}
启动:

我正在从JS应用程序向
http://localhost:8080/login
,我认为这在本例中无关紧要,但我使用的是MithrilJS请求:

m.request({
    method: "POST",
    url: "http://localhost:8080/login",
    body: {username: login, password: pass}
})
.then((result) => {
    UserLogin.loggedIn = true;
})
.catch(error => {
    console.log(error);
});
我得到的答复(2个出于某种原因):

现在有趣的是,响应包含html(注意,我的代码中没有这个html)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Please sign in</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
    <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
  </head>
  <body>
     <div class="container">
      <form class="form-signin" method="post" action="/login">
        <h2 class="form-signin-heading">Please sign in</h2>
<div class="alert alert-danger" role="alert">Invalid credentials</div>        <p>
          <label for="username" class="sr-only">Username</label>
          <input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
        </p>
        <p>
          <label for="password" class="sr-only">Password</label>
          <input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
        </p>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      </form>
</body></html>

请登录
请登录
无效凭证
用户名

密码

登录
知道我在哪里失败了吗

编辑:

谢谢你的回答,虽然它并没有完全回答我的想法,但它确实把我引向了正确的方向

我的主要问题是我有两个独立的项目:1)spring启动项目2)JS应用程序。JS应用程序本身包含表单html(本例中为JS),因为我不希望任何前端代码是或来自后端(SpringBoot项目),而所有登录逻辑都在SpringBootSpringSecurity中

如果我禁用formLogin(我必须这么做,不使用spring登录表单),我就不会得到/login端点

总而言之,我希望在绕过spring登录表单的同时使用spring安全性(这样后端包含登录逻辑,可以通过任何表单访问,或者这就是想法)

虽然我还没有完全到达那里,但我正在到达那里


对于任何好奇的人来说,这是一篇有帮助的文章:

HTML是默认的登录表单

为什么定义formLogin()

您必须在授权标头而不是正文中发送用户名和密码


HTML是默认的登录表单

为什么定义formLogin()

您必须在授权标头而不是正文中发送用户名和密码


您正在尝试使用ajax进行身份验证,因此无法重定向到依赖于服务器响应的任何其他页面,您应该在JS中执行此操作(例如
window.location.href

现在,让我们谈谈您案例中的
表单登录
。根据您的配置启用
UsernamePasswordAuthenticationFilter

.formLogin()
    .defaultSuccessUrl("/", true)
    .permitAll()
此筛选器将从请求参数获取用户名和密码

protected String obtainUsername(HttpServletRequest request) {
    return request.getParameter(usernameParameter);
}
protected String obtainPassword(HttpServletRequest request) {
    return request.getParameter(passwordParameter);
}
但是您正试图向服务器发送json正文,因此它无法获得正确的凭据。您应该将其更改为
表单
请求

下一个是关于失败重定向url,现在您应该知道ajax不能重定向到其他页面,您配置中的默认
failureHandler
将错误地重定向到登录页面,现在您使用的是ajax,因此您只需获取HTML,我想您可以根据标题验证请求(例如401),这里有一个例子

.formLogin()
    .failureHandler(new SimpleUrlAuthenticationFailureHandler())
以下是
SimpleRuthenticationFailureHandler

if (defaultFailureUrl == null) {
    logger.debug("No failure URL set, sending 401 Unauthorized error");
    response.sendError(HttpStatus.UNAUTHORIZED.value(),
                HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
您可以根据标题和正文获得结果

现在我想您应该知道,您的配置中的
defaultSuccessUrl
不会像您预期的那样工作。您需要实现自己的
AuthenticationSuccessHandler


最后一个是关于您的
表单
身份验证,表单身份验证大部分是基于cookie的,我认为您所有的请求都应该包含成功登录后发送到服务器的cookie。也许你可以改为研究。

你正在尝试使用ajax进行身份验证,因此你不能重定向到依赖于服务器响应的任何其他页面,你应该在JS中这样做(例如
window.location.href

现在,让我们谈谈您案例中的
表单登录
。根据您的配置启用
UsernamePasswordAuthenticationFilter

.formLogin()
    .defaultSuccessUrl("/", true)
    .permitAll()
此筛选器将从请求参数获取用户名和密码

protected String obtainUsername(HttpServletRequest request) {
    return request.getParameter(usernameParameter);
}
protected String obtainPassword(HttpServletRequest request) {
    return request.getParameter(passwordParameter);
}
但是您正试图向服务器发送json正文,因此它无法获得正确的凭据。您应该将其更改为
表单
请求

下一个是关于失败重定向url,现在您应该知道ajax不能重定向到其他页面,您配置中的默认
failureHandler
将错误地重定向到登录页面,现在您使用的是ajax,因此您只需获取HTML,我想您可以根据标题验证请求(例如401),这里有一个例子

.formLogin()
    .failureHandler(new SimpleUrlAuthenticationFailureHandler())
以下是
SimpleRuthenticationFailureHandler

if (defaultFailureUrl == null) {
    logger.debug("No failure URL set, sending 401 Unauthorized error");
    response.sendError(HttpStatus.UNAUTHORIZED.value(),
                HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
您可以根据标题和正文获得结果

现在我想您应该知道,您的配置中的
defaultSuccessUrl
不会像您预期的那样工作。您需要实现自己的
AuthenticationSuccessHandler

最后一个是关于您的
表单
身份验证,表单身份验证大部分是基于cookie的,我认为您所有的请求都应该包含成功登录后发送到服务器的cookie。也许你可以研究一下