Reputation: 55
Iam implementing a basic authentication for Spring Boot application and iam defining my credentials in application.properties class but I want to hash-encode the password and then check if the hash is the same as the hash for the password in application.properties then I can login. If possible to do all of the logic in the configure method then it would be great.
application.properties:
user.name=test
user.password={noop}example
SecurityConfig class:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private AuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic()
.and().sessionManagement().and().authenticationProvider(authenticationProvider)
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
UPDATED CODE
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Value("${security.user.password}")
private String password;
@Value("${security.user.name}")
private String username;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated()
.and().logout().and().httpBasic().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
passwordEncoder(passwordEncoder()).withUser(username).password(password);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public String generateHashedPassword(String password) {
return BCrypt.hashpw(password, BCrypt.gensalt(10));
}
}
UPDATE 2
Currently the way it works now is when i start the application, i visit localhost:8080 then a login popup appears and i type the username and password (that are defined in application.properties)
if I type the right username and password i get logged in but if i manage to login with the username and password defined in application.properties then whats the point with hashing the password? I was thinking more like having a list of hashed keys and compare the input password with the list and if success then login.
Upvotes: 1
Views: 6777
Reputation: 2030
Since you want to define your credentials in properties file, I guess you can take advantage of inmemory authentication. Try the following:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private AuthenticationProvider authenticationProvider;
@Value("${user.name}")
private String userName;
@Value("${user.password}")
private String userHashedPassword; // hashed password
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic()
.and().sessionManagement().and().authenticationProvider(authenticationProvider)
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth
.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser(userName)
.password(userHashedPassword);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Please, note, that in this case your password should be encrypted with BCryptPasswordEncoder
first, and then you should put it into properties file (you can use its encoder.encode("password")
method). Or you can use any other implementation of PasswordEncoder
if you want. I've also noticed that you're using some custom autenticationProvider. Not sure how it works since you didnt share the code, and not sure that it will get along with inmemory autentication. But, anyway, I think it worth a shot and this is the right way to go in your scenario.
Hope it helps.
Upvotes: 4