spring - Spring安全登录失败错误重定向并且没有错误消息
问题描述
我正在尝试构建一个简单的登录表单(JS)和用户 Spring 安全性。据我了解,当登录失败时,它应该重定向到登录页面(或者仅适用于引导项目中的 JSP 登录页面?)但它无法做到这一点。并且查询错误字符串参数也是空的。
我的弹簧安全配置:
@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;
}
}
引导:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
从 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出于某种原因)我得到:
http://localhost:8080/login?error
Request Method: OPTIONS
Response is empty
error string is also empty
http://localhost:8080/login?error
Request Method: GET
error String is empty
现在有趣的部分是,响应包含 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>
任何想法我在哪里失败?
编辑:
感谢您的回答,虽然它没有完全回答我的想法,但它确实引导我走向正确的方向。
我的主要问题是我有 2 个独立的项目:1)一个 Spring Boot 项目 2)一个 JS 应用程序。JS 应用程序包含表单 html 本身(或本例中的 JS),因为我不希望任何前端代码来自或来自后端(spring boot 项目),而所有登录逻辑都在 spring boot spring security 中。
如果我禁用 formLogin (我必须这样做,不使用弹簧登录表单)我没有 /login 端点。
总结一下,我想在绕过spring登录表单的同时使用spring security(这种方式后端包含登录逻辑,可以通过任何表单访问,或者就是这个想法)。
虽然我还没有完全到达那里,但我正在到达那里。
对于任何好奇的人,这篇文章有帮助:没有登录表单的弹簧安全性
解决方案
您正在尝试使用 ajax 进行身份验证,因此您不能重定向到依赖于服务器响应的任何其他页面,您应该在您的 JS(例如window.location.href
)中执行此操作。
现在让我们谈谈form login
你的情况。根据UsernamePasswordAuthenticationFilter
您的配置启用。
.formLogin()
.defaultSuccessUrl("/", true)
.permitAll()
此过滤器将从请求参数中获取用户名和密码。
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
但是您正在尝试将 json 正文发送到服务器,因此它无法获得正确的凭据。您应该将其更改为form
请求。
下一个是关于失败重定向 url,现在你应该知道 ajax 不能重定向到其他页面,failureHandler
你配置中的默认设置会重定向到登录页面,现在你正在使用 ajax,所以你可以得到 HTML ,我认为您可以仅根据标头(例如 401)验证请求,这是一个示例。
.formLogin()
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
这是代码SimpleUrlAuthenticationFailureHandler
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
您可以根据标题和正文获得结果。
现在我认为你应该知道defaultSuccessUrl
你的配置不会像你期望的那样工作。你需要实现你自己的AuthenticationSuccessHandler
.
最后一个是关于你的form
身份验证,表单身份验证大部分是基于cookie的,我认为你所有的请求都应该包含登录成功后向服务器发送的cookie。也许你可以研究JWT来代替。
推荐阅读
- go - 使用函数类型组
- spring-boot - ResourceServerTokenServicesConfiguration 中的 userInfoRestTemplateFactory 需要单个 bean,但找到了 4 个
- django - 检查用户是否具有列表权限并将结果转换为字典的有效方法
- java - 即使映射看起来正确,休眠映射异常
- docker - 在 docker compose 文件中设置 .env 变量时遇到问题
- django - 根据每个 DevicePart 模型计算 django 模型设备中的总数,包括数量
- django - 如果已经在 django 中使用任何社交身份验证登录,如何从登录页面重定向登录用户?
- awk - 如何执行将环境变量和变量参数从带有 xargs 的文件中合并的命令?
- production - Laravel Telescope 没有与 Laravel Voyager 一起工作。如何在 Laravel 7 中保护 /telescope/* 路线?
- django - 如何在 django 中创建下载视图