英文:
Spring Security login fails despite correct username and password
问题
以下是您提供的内容的翻译:
早上好,我在使用Spring Security的应用程序中遇到了登录问题。每次我尝试登录(即使用户名和密码是正确的),应用程序都会将我重定向到失败的URL(在我的情况下是:/login?error=true)。密码使用BCrypt进行加密,并且我在使用MySQL数据库存储它们。
该应用程序基于《Spring in Action 5》中的代码:
https://github.com/habuma/spring-in-action-5-samples/tree/master/ch04/tacos
我的代码:
User类
@Entity
@Data
@NoArgsConstructor
@Table(name = "Users")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String email;
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("userService")
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/calendar")
.hasRole("USER")
.antMatchers("/", "/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/calendar")
.failureUrl("/login?error=true")
.and()
.logout()
.logoutSuccessUrl("/");
}
}
用户服务
@Service
public class UserService implements UserDetailsService {
private UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository){
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user != null){
return user;
}
throw new UsernameNotFoundException("Username not found: " + username);
}
}
控制器
@Controller
@RequestMapping("/register")
public class UserController {
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
@Autowired
public UserController(UserRepository userRepository, PasswordEncoder passwordEncoder){
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@ModelAttribute
public void calendar(Model model){
model.addAttribute("user", new User());
}
@GetMapping
public String register(){
return "register";
}
@PostMapping
public String addUser(@ModelAttribute User user){
User newUser = new User(user.getUsername(),passwordEncoder.encode(user.getPassword()),user.getEmail());
userRepository.save(newUser);
return "redirect:/login";
}
}
登录表单(Thymeleaf)
<form th:method="POST" th:action="@{/login}">
<div class="formInputs">
<label for="username">Username</label>
<input id="username" name="username" type="text">
</div>
<div class="formInputs">
<label for="password">Password</label>
<input id="password" name="password" type="password">
</div>
<div style="clear: both"></div>
<input type="submit" value="Log in">
</form>
注册表单
<form method="POST" th:action="@{/register}" th:object="${user}">
<div class="formInputs">
<label for="username">Username</label>
<input id="username" type="text" th:field="*{username}">
</div>
<div class="formInputs">
<label for="password">Password</label>
<input id="password" type="password" th:field="*{password}">
</div>
<div class="formInputs">
<label for="email">Email</label>
<input id="email" type="email" th:field="*{email}">
</div>
<div style="clear: both"></div>
<input type="submit" value="Register">
<input type="reset" value="Reset">
</form>
如果有人能帮助我找到解决方案,我将不胜感激,提前谢谢您。
英文:
Good morning, I have encountered problem with logging into app which uses Spring Security. Every time i try to log in (even though username and password are correct), app redirects me to failure url (in my case it's: /login?error=true). Passwords are encrypted with BCrypt and I'm using MySQL Database to store them.
App is based on code from Spring in Action 5:
<https://github.com/habuma/spring-in-action-5-samples/tree/master/ch04/tacos>
My code:
User class
@Entity
@Data
@NoArgsConstructor
@Table(name = "Users")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String email;
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("userService")
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/calendar")
.hasRole("USER")
.antMatchers("/","/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/calendar")
.failureUrl("/login?error=true")
.and()
.logout()
.logoutSuccessUrl("/");
}
}
User service
@Service
public class UserService implements UserDetailsService {
private UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository){
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user != null){
return user;
}
throw new UsernameNotFoundException("Username not found: "+username);
}
}
Controller
@Controller
@RequestMapping("/register")
public class UserController {
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
@Autowired
public UserController(UserRepository userRepository, PasswordEncoder passwordEncoder){
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@ModelAttribute
public void calendar(Model model){
model.addAttribute("user", new User());
}
@GetMapping
public String register(){
return "register";
}
@PostMapping
public String addUser(@ModelAttribute User user){
User newUser = new User(user.getUsername(),passwordEncoder.encode(user.getPassword()),user.getEmail());
userRepository.save(newUser);
return "redirect:/login";
}
}
Login form (Thymeleaf)
<form th:method="POST" th:action="@{/login}">
<div class="formInputs">
<label for="username">Username</label>
<input id="username" name="username" type="text">
</div>
<div class="formInputs">
<label for="password">Password</label>
<input id="password" name="password" type="password">
</div>
<div style="clear: both"></div>
<input type="submit" value="Log in">
</form>
Registration form
<form method="POST" th:action="@{/register}" th:object="${user}">
<div class="formInputs">
<label for="username">Username</label>
<input id="username" type="text" th:field="*{username}">
</div>
<div class="formInputs">
<label for="password">Password</label>
<input id="password" type="password" th:field="*{password}">
</div>
<div class="formInputs">
<label for="email">Email</label>
<input id="email" type="email" th:field="*{email}">
</div>
<div style="clear: both"></div>
<input type="submit" value="Register">
<input type="reset" value="Reset">
</form>
If someone could help me find a solution i would be grateful, thank you in advance.
答案1
得分: 0
确保您的用户返回enabled = true
,以及isAccountNonExpired = true
(以及所有其他属性,比如isAccountNonLocked)。同时返回一个空权限列表
,而不是null。
否则,Spring Security将视您的用户为已禁用/已锁定/其他状态,不允许您登录。
英文:
Make sure your user returns enabled = true
, as well as isAccountNonExpired = true
(and all others as well, like isAccountNonLocked). Also return an empty list of authorities
, not null.
Otherwise Spring Security will treat your user as disabled/locked/whatever and not allow you to login.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论