我正在学习如何使用spring security来构建登录功能,我得到了如下错误“无效的用户名或密码”:
原因:java.lang.NullPointerException:无法调用“com.thang.repository.AccountRepository.findByUsername(String)”,因为“this.accountRepository”在com.thang.service.CustomAccountDetailsService.loadUserByUsername(CustomAccountDetailsService.java:27)~[classes/:na] at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:103)~[spring-security-core-6.1.1.jar:6.1.1]为null...省略60个公共帧
我试着在谷歌上找到修复它的方法,但它不起作用,希望你能帮助我x1c 0d1x
Account.java
package com.thang.entity;
import java.util.Set;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name= "users")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private String password;
public Account(String name, String username, String email, String password, Set<Role> roles) {
super();
this.name = name;
this.username = username;
this.email = email;
this.password = password;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles;
}
字符串
AccountRepository.java
package com.thang.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.thang.entity.Account;
public interface AccountRepository extends JpaRepository<Account, Long>{
Optional<Account> findByUsername(String username);
Boolean existsByEmail(String email);
Optional<Account> findByUsernameOrEmail(String username, String email);
boolean existsByUsername(String username);
}
型
CustomAccountDetailsService.java
package com.thang.service;
import lombok.AllArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.thang.entity.Account;
import com.thang.repository.AccountRepository;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class CustomAccountDetailsService implements UserDetailsService {
private AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not exists by Username"));
Set<GrantedAuthority> authorities = account.getRoles().stream()
.map((role) -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
return new org.springframework.security.core.userdetails.User(
username,
account.getPassword(),
authorities
);
}
}
型
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" th:href="@{/index}">Login System</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-togger-icon"></span>
</button>
</div>
</nav>
<br /><br />
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<div th:if="${param.error}">
<div class="alert alert-danger">Invalid Username or Password</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-success">You have been logout.</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="text-center">Login Form</h2>
</div>
<div class="card-body">
<form method="post" role="form" th:action="@{/login}" class="form-horizontal">
<div class="form-group mb3">
<label>User Name</label>
<input
type="text"
id="username"
name="username"
class="form-control"
placeholder="Enter Username"
/>
</div>
<div class="form-group mb3">
<label>Password</label>
<input
type="password"
id="password"
name="password"
class="form-control"
placeholder="Enter password"
/>
</div>
<br>
<div class="form-group mb-3">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
型
SecurityConfig.java
package com.thang.security;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static org.springframework.security.config.Customizer.*;
@Configuration
@AllArgsConstructor
public class SecurityConfig{
@SuppressWarnings("unused")
private UserDetailsService userDetailsService;
@Bean
static PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(withDefaults())
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
).formLogin(
form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/handover")
.permitAll()
).logout(
logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll()
);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}
型
1条答案
按热度按时间gtlvzcf81#
AccountRepository
缺少一个@Repository
注解,所以它不是一个springbean,这意味着它不会被注入到服务中,导致它为null。