I am newbie to spring security and trying to implement spring security in my spring-boot web application. I am following SpringSecurity blog to implement security through user
and role
using database. The code also found at github . This blog says
Note
We will pass the bean UserRepository to the UserDetailsService because this bean will be loaded before the repository is loaded, so we might get the useeRepository bean as null in out SSUserDetailsService.
NB: I have change SSUserDetailsService
to WebUserDetailsService
I have
Entity:
User
andRole
creates 3 tables (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
to fetch data from database
/*----------------------------------- User repository ----------------------------------*/
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
Security Configuration:
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
Problems:
userRepository.findByUsername()
returns null for valid credentials in WebUserDetailsService
> loadUserByUsername()
. I observed that if I put following code (commenting out User user = userRepository.findByUsername(username);
line) as test purpose then saw that there is no error for validation. That is userRepository
is not working. What should I do to pull a user by username using userRepository
?
@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"); } }
I call userRepository.findByUsername()
in my "/"
URL mapping to test whether repository is working or not. I figured out there is an error for toString()
declared in User
. There is no error if I commented out ", roles=" + roles +
line. How do I load role with corresponding user? Have a look at toString() in User
@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\\'' + ", password='" + password + '\\'' + ", enabled=" + enabled + ", roles=" + roles + '}'; }
Create a data.sql
and place it in your src/main/resources
folder. It must have the following content at minimum.
INSERT INTO user(username, password, enabled) VALUES('abc@bca.com', 'abc123', true);
INSERT INTO role(role) VALUES('ROLE_USER');
INSERT INTO user_roles(user_id, role_id) VALUES(1, 1);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.