我有一个带有 Spring Data JPA MySQL 的简单 Spring Boot 2.xx 应用程序,我必须使用 Spring Security(尤其是 Java 配置)来保护这个 Web 应用程序,在这方面,我在网上找到了大量资源来完成工作,但是 <强>徒劳强>,有些例子太复杂而难以理解,而其他例子从来没有在我这边起作用。我想出了这个secure-spring-demo ,这也不起作用。一些代码片段是
WebSecurityConfig 类是
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/login*", "/register", "/").anonymous()
.antMatchers("/secure/*").hasAnyAuthority("ADMIN").anyRequest().authenticated()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.logout().logoutSuccessUrl("/login");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
而 UserDetailsServiceImpl 类是
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserService userService;
@Autowired
public UserDetailsServiceImpl(UserService userService) {
this.userService = userService;
}
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userService.findByUserEmail(s);
if (user == null){
throw new UsernameNotFoundException("User with " + s + " not found!");
}
return new org.springframework.security.core.userdetails.User(
user.getUserEmail(), user.getUserPassword(), user.getRoles());
}
}
Controller 是
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private SecurityService securityService;
//Omitting other mappings
@GetMapping(value = "/login")
public String getLogin(Model model,
@RequestParam(value = "error", required = false) String error){
if (null != error && error.equalsIgnoreCase("true")){
model.addAttribute("loginError", "Unable to Login");
}
return "login";
}
@PostMapping(value = "/login")
public String postLogin(@RequestParam(value = "userEmail") String userEmail,
@RequestParam(value = "userPassword") String userPassword){
logger.debug(userEmail + " and " + userPassword );
boolean loginResult = securityService.login(userEmail, userPassword);
return (loginResult ? "redirect:/secure/home" : "redirect:/login?error=true");
}
}
这样一来,所有用户都无法使用正确的凭据登录。
最佳答案
我在您的代码中发现的主要问题是没有从 thymeleaf 模板传递“用户名”和“密码”属性,因为它应该与精确的凭据属性匹配才能验证对象。因此您的登录表单将如下所示:
<form th:method="post" th:action="@{/login}" enctype="utf8">
<input th:type="email" name="username" placeholder="Email" required="">
<input th:type="password" name="password" placeholder="Password" required="">
<button th:type="submit" name="submit"> Login </button>
<span>You Have No Account? <a th:href="@{/register}"> Create An Account</a></span>
</form>
由于参数已更改,因此您还需要更改 Controller 属性:
@PostMapping(value = "/login") public String postLogin(@RequestParam(value = "username") String userEmail, @RequestParam(value = "password") String userPassword){ logger.debug(userEmail + " and " + userPassword ); boolean loginResult = securityService.login(userEmail, userPassword); return (loginResult ? "redirect:/secure/home" : "redirect:/login?error=true"); }
关于java - 在 Spring Security 中使用 UserDetails 实现登录不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53029633/