Ashish
Ashish

Reputation: 341

Loading Properties with same prefix in Spring Security using Spring Boot

I am authenticating an application with a login page using Spring Seurity and Spring Boot. I am storing user credentials in a properties file (until we finalize a Database) with password in encrypted for starting 5 users.

Here is my properties file

User.properties

my.web.user[0].username=John
my.web.user[0].password=$2y$12$V
my.web.user[0].role=ADMIN,USER

my.web.user[1].username=Johny
my.web.user[1].password=$2y$12$5C
my.web.user[1].role=ADMIN,USER

my.web.user[2].username=McCain
my.web.user[2].password=$2y$12$ERL8mf5.
my.web.user[2].role=USER

So now we can add as many users we want but in this array format. Now, I am loading this properties file in Spring Boot.

MyWebApplication.java

@SpringBootApplication
@ComponentScan(basePackages = { "com.myorg.module" })
@EnableConfigurationProperties(UserConfig.class)  
public class MyWebApplication {

    public static void main(String[] args) {

        ApplicationContext appCtxt = SpringApplication.run(MyWebApplication.class, args);
    }
}

UserConfig.java

@Configuration
@PropertySource("user.properties")
@ConfigurationProperties(prefix="my.web")
public class UserConfig {

    private List<User> user;

    /**
     * @return the user
     */
    public List<User> getUser() {
        return user;
    }

    /**
     * @param user the user to set
     */
    public void setUser(List<User> user) {
        this.user = user;
    }

}

UserDetailsServiceImpl

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import UserConfig;
import User;

@Component
public class UserDetailsServiceImpl implements UserDetailsService{

    @Autowired
    private UserConfig userConfig;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = findUserByUsername(username);
        UserBuilder userBuilder = null;

        if(user != null) {
            userBuilder = org.springframework.security.core.userdetails.User.withUsername(username);
            userBuilder.password(new BCryptPasswordEncoder().encode(user.getPassword()));
            userBuilder.roles(user.getRoles());
        }else {
            throw new UsernameNotFoundException("User Not Found");
        }

        return userBuilder.build();
    }

    private User findUserByUsername(String username) {
        System.out.println(userConfig);
        return userConfig.getUser().get(0);
    }

}

Now when I am loading the UserConfig into my UserDetailsServiceImpl using @Autowired. In this case, I am getting userConfig as null. However, when I am putting debug points into getter/setter in UserConfig. I can see that it is populating object with properties contents on Container startup. But later on it vanishes and make it NULL.

Can anyone let me know where am I making mistake?

Thanks in advance.

Upvotes: 0

Views: 693

Answers (1)

Ashish
Ashish

Reputation: 341

There are couple of learnings which I had on this.

  1. WebSecurityConfigurerAdapter subclass - This child class should have @Autowired the UserDetailsService interface. In my case, I wrote UserDetailsServiceImpl which is the implementation of UserDetailsService interface.
  2. Properties' array key name must match with the variable name of the @Configuration class. In my case, in properties, I had

    my.web.user[0].username=John

and the variable name must be the same in @Configuration class like

@Configuration
@ConfigurationProperties(prefix="my.web")
@PropertySource("user.properties")
public class UserConfig {

    private List<User> **user**;

And then it suddenly started working.

P.S. - I did lot of googling and research but nothing worked. Then I read this document 3 times to get it worked.

Upvotes: 1

Related Questions