Spring 启动 post 请求处理程序未触发
Spring Boot post request handler not firing
感谢您调查我的问题。
我正在练习 Spring 启动和 Spring 安全。我已经通过基本注册创建了一个简单的项目,但我无法登录工作。我正在尝试使用 POST: /login
方法手动登录用户,但该方法未触发。当我尝试使用 POST: /login 登录时,它只是 302 重定向到 GET /login
。我很确定我已经正确设置了安全配置和方法注释。但是 post 方法甚至不是 运行ning。 (我知道,因为我的 post 方法中有一个打印语句,即使在我启动应用程序并创建用户并登录时也不会打印任何内容。)我该如何解决这个问题?
(我不确定 post 方法是否真的能让用户正确登录,我只是想把它变成 运行 这样我就可以弄清楚那部分了。)
完整代码在这里:https://github.com/Skyler827/SpacePong/tree/7530377a634f1a2fe55ce490402d947616439e72
安全配置器方法:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.loginPage("/login")
.failureUrl("/login?error=true")
.successForwardUrl("/")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
应该工作但没有工作的控制器:
@Controller
@RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
@GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
@PostMapping
public String postLogin(@ModelAttribute("playerdto") PlayerDto playerDto, Model model) {
System.out.println("running postLogin()");
Player player = playerService.getPlayerByName(playerDto.getUsername());
if (player == null) {
model.addAttribute("error", "invalid login");
return "login";
}
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
playerDto.getUsername(), playerDto.getPassword());
Authentication auth = authManager.authenticate(authReq);
return "redirect:/";
}
}
我找到了解决方法;我仍然无法执行自定义控制器方法,但我可以让用户登录,这是我的目标。
这个项目用的是Java17,顺便说一下。
我通过删除控制器中的整个postLogin()
方法并删除configure(HttpSecurity http)
方法中formLogin()
下的所有配置来启用用户登录。一旦我这样做了,我就不再有我的自定义登录页面,但我有一个默认登录页面,而且它确实有效。
我试图将 .loginPage("/login")
指令重新添加到配置方法中以指定自定义登录页面,但这导致登录表单返回到 302 重定向到自身,即使在我不正确的控制器被删除之后.
我更正的配置方法:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
我更正的控制器:
@Controller
@RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
@GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
}
Form Login 示例中有一个如何配置自定义登录页面的示例。一些常见问题是未使用正确的表单操作(例如 action="/login"
)、错误命名的表单输入(例如 name="username"
、name="password"
)和缺少隐藏的 CSRF 输入(例如 type="hidden" name="_csrf" value="..."
) .
要记住的最重要的细节是,在配置 .formLogin()
时,Spring 安全的过滤器链正在处理 POST /login
请求并在您的控制器之前返回响应,即使 .antMatchers("/login").permitAll()
被使用。这就是为什么您看不到任何影响您的控制器方法的原因。
虽然在大多数情况下我不推荐它,但您可以通过简单地省略 DSL 的 .formLogin()
部分来尝试自己处理 POST /login
请求。执行此操作时,您有责任自行设置 SecurityContext
。
感谢您调查我的问题。
我正在练习 Spring 启动和 Spring 安全。我已经通过基本注册创建了一个简单的项目,但我无法登录工作。我正在尝试使用 POST: /login
方法手动登录用户,但该方法未触发。当我尝试使用 POST: /login 登录时,它只是 302 重定向到 GET /login
。我很确定我已经正确设置了安全配置和方法注释。但是 post 方法甚至不是 运行ning。 (我知道,因为我的 post 方法中有一个打印语句,即使在我启动应用程序并创建用户并登录时也不会打印任何内容。)我该如何解决这个问题?
(我不确定 post 方法是否真的能让用户正确登录,我只是想把它变成 运行 这样我就可以弄清楚那部分了。)
完整代码在这里:https://github.com/Skyler827/SpacePong/tree/7530377a634f1a2fe55ce490402d947616439e72
安全配置器方法:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.loginPage("/login")
.failureUrl("/login?error=true")
.successForwardUrl("/")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
应该工作但没有工作的控制器:
@Controller
@RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
@GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
@PostMapping
public String postLogin(@ModelAttribute("playerdto") PlayerDto playerDto, Model model) {
System.out.println("running postLogin()");
Player player = playerService.getPlayerByName(playerDto.getUsername());
if (player == null) {
model.addAttribute("error", "invalid login");
return "login";
}
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
playerDto.getUsername(), playerDto.getPassword());
Authentication auth = authManager.authenticate(authReq);
return "redirect:/";
}
}
我找到了解决方法;我仍然无法执行自定义控制器方法,但我可以让用户登录,这是我的目标。
这个项目用的是Java17,顺便说一下。
我通过删除控制器中的整个postLogin()
方法并删除configure(HttpSecurity http)
方法中formLogin()
下的所有配置来启用用户登录。一旦我这样做了,我就不再有我的自定义登录页面,但我有一个默认登录页面,而且它确实有效。
我试图将 .loginPage("/login")
指令重新添加到配置方法中以指定自定义登录页面,但这导致登录表单返回到 302 重定向到自身,即使在我不正确的控制器被删除之后.
我更正的配置方法:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
我更正的控制器:
@Controller
@RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
@GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
}
Form Login 示例中有一个如何配置自定义登录页面的示例。一些常见问题是未使用正确的表单操作(例如 action="/login"
)、错误命名的表单输入(例如 name="username"
、name="password"
)和缺少隐藏的 CSRF 输入(例如 type="hidden" name="_csrf" value="..."
) .
要记住的最重要的细节是,在配置 .formLogin()
时,Spring 安全的过滤器链正在处理 POST /login
请求并在您的控制器之前返回响应,即使 .antMatchers("/login").permitAll()
被使用。这就是为什么您看不到任何影响您的控制器方法的原因。
虽然在大多数情况下我不推荐它,但您可以通过简单地省略 DSL 的 .formLogin()
部分来尝试自己处理 POST /login
请求。执行此操作时,您有责任自行设置 SecurityContext
。