Ich bin ein Neuling, um die Sicherheit zu erhöhen und die Federsicherheit in meiner Spring-Boot-Webanwendung zu implementieren. Ich folge SpringSecurity Blog, um Sicherheit durch user
und role
mithilfe der Datenbank zu implementieren. Der Code wurde auch bei github gefunden. Dieser Blog sagtRepository gibt null in Spring Security zurück
Hinweis
Wir werden die Bohne UserRepository zum UserDetailsService geben, da diese Bohne geladen werden, bevor das Repository geladen wird, so könnten wir die useeRepository Bohne als null in erhalten aus SSUserDetailsService.
N. B: Ich habe Änderung SSUserDetailsService
-WebUserDetailsService
Ich habe
Entity:
User
undRole
schafft 3-Tabellen (user
,role
&user_roles
)
/*------------------------------------- User entity -------------------------------------*/
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String username;
private String password;
private boolean enabled;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
// getters, setters & toString
}
/*------------------------------------- Role entity -------------------------------------*/
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String role;
@ManyToMany(mappedBy = "role", fetch = FetchType.LAZY)
private Set<User> users;
//getters, setters & toString
}
Repository:
UserRepository
zu holen Daten aus der Datenbank
/*----------------------------------- User repository ----------------------------------*/
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
Sicherheitskonfiguration:
WebSecurityConfigurer
&WebUserDetailsService
/*------------------------------- WebSecurityConfigurer -------------------------------*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private UserRepository userRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsServiceBean());
}
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return new WebUserDetailsService(userRepository);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/img/**", "/js/**").permitAll()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAuthority("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username").passwordParameter("password").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
;
}
}
/*------------------------------- WebUserDetailsService -------------------------------*/
@Transactional
public class WebUserDetailsService implements UserDetailsService {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(WebUserDetailsService.class);
private UserRepository userRepository;
public WebUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
User user = userRepository.findByUsername(username);
if (user == null) {
LOGGER.debug("user not found with the provided username");
return null;
}
LOGGER.debug(" user from username " + user.toString());
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
}
catch (Exception e){
throw new UsernameNotFoundException("User not found");
}
}
private Set<GrantedAuthority> getAuthorities(User user){
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role : user.getRoles()) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole());
authorities.add(grantedAuthority);
}
LOGGER.debug("user authorities are " + authorities.toString());
return authorities;
}
}
Database Connectivity:
application.properties
#defauls
#security.user.name=user
#security.user.password=password
#security.user.role=ROLE_USER, ROLE_ADMIN
#configurations
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
#initializations
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
#credentials
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/spring_boot_security
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.schema=classpath:/data/schema.sql
#query-configurations
spring.datasource.maxActive=10
spring.datasource.max-idle=4
spring.datasource.min-idle=2
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1
spring.datasource.time-between-eviction-runs-millis=60000
spring.datasource.min-evictable-idle-time-millis=300000
#server-configurations
hazelcast.server.address=127.0.0.1
Probleme:
userRepository.findByUsername()
gibt null für gültige Anmeldeinformationen inWebUserDetailsService
>loadUserByUsername()
zurück. Ich habe beobachtet, dass, wenn ich den folgenden Code (User user = userRepository.findByUsername(username);
Linie) als Testzweck setzen Sie dann sah, dass es keinen Fehler für die Validierung gibt. Das istuserRepository
funktioniert nicht. Was soll ich tun, um einen Benutzer mit dem BenutzernamenuserRepository
zu ziehen?@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { try { //User user = userRepository.findByUsername(username); Role role = new Role(); role.setId(1L); role.setRole("USER"); Set<Role> roles = new HashSet<>(); roles.add(role); User user = new User(); user.setEnabled(true); user.setId(1L); user.setPassword("12345"); user.setUsername("johir1"); user.setRoles(roles); if (user == null) { LOGGER.debug("user not found with the provided username"); return null; } LOGGER.debug(" user from username " + user.toString()); return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user)); } catch (Exception e){ throw new UsernameNotFoundException("User not found"); } }
Ich nenne
userRepository.findByUsername()
in meiner"/"
URL-Zuordnung zu testen, ob Repository arbeitet oder nicht. Ich habe herausgefunden, dass ein Fehler fürtoString()
inUser
gemeldet wurde.Es gibt keinen Fehler, wenn ich die Zeile", roles=" + roles +
auskommentiert habe. Wie lade ich Rolle mit dem entsprechenden Benutzer? Werfen Sie einen Blick auf toString() in Benutzer@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", enabled=" + enabled + ", roles=" + roles + '}'; }
Gibt es ein Problem, viele-zu-viele-Mapping? – Johir
getRoles gibt nichts zurück, solange Benutzer userRepository.findByUsername() gefunden hat. Warum? – Johir