0

EDIT:

The simplest way I found:

@SuppressWarnings("deprecation")
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery(
                "SELECT username, password, abilitazione FROM public.utenti WHERE username=?")
        .passwordEncoder(passwordEncoder())
        .authoritiesByUsernameQuery(
                "SELECT username, ruolo FROM public.ruoli_utente WHERE username=?");
    } 

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //omitted for brevity
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }

in my dao class I add users like this:

public void addElement(Utente u) {
    String password = u.getPassword();
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    String hashedPassword = passwordEncoder.encode(password);
    u.setPassword(hashedPassword);
    jdbcTemplate.update("INSERT INTO public.utenti(username, password, abilitazione, email, nome, cognome) VALUES (?, ?, ?, ?, ?, ?)",
    new Object[] {u.getUsername(), u.getPassword(), u.getAbilitazione(), u.getEmail(), u.getNome(), u.getCognome()});

}

I want to encrypt and decrypt the password in a super easy way, doesn't matter if it's not super secure, it just have to be secure for my purpose. So, in database I added encrypted passwords. When the user authenticate it doesn't recognize the password, even if I decode it. I did it like this:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery(
                "SELECT username, decode(password,'base64'), abilitazione FROM public.utenti WHERE username=?")
        .authoritiesByUsernameQuery(
                "SELECT username, ruolo FROM public.ruoli_utente WHERE username=?");
    } 
}

It could work in similar ways (decoding directly in usersByUsernameQuery method), or I must declare some beans for decoding?

1 Answer 1

2

I did it in this way and seems quite clean and open to changes.

In your Application class:

@Bean
public ApplicationSecurity applicationSecurity() {
    return new ApplicationSecurity();
}  

Your application security class

public class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailSecurityService userDetailSecurityService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().antMatchers("/ace/**",
                                                            "/app/**",
                                                            "/jquery/**",
                                                            "/bootstrap/**",
                                                            "/font-awesome/**",
                                                            "/jstree/**",
                                                            "/img/**").permitAll().anyRequest()
            .fullyAuthenticated();

        http.csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=1").permitAll().defaultSuccessUrl("/configurator").and().logout().permitAll();

        http.headers().frameOptions().disable().addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS", "SAMEORIGIN"));
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws  Exception {
        auth.userDetailsService(userDetailSecurityService).passwordEncoder(passwordEncoder());
    }


     @Bean
     public PasswordEncoder passwordEncoder(){
         return new MD5PasswordEncoder();
     }

}

And the class MDPasswordEncoder, or any implementation you want to use:

public class MD5PasswordEncoder implements PasswordEncoder {

     @Override
     public String encode(CharSequence charSequence) {
         String encPass = "";
        try {
             MessageDigest md = MessageDigest.getInstance("MD5");
             byte[] digest = md.digest(charSequence.toString().getBytes());
             byte[] b64 = Base64.encodeBase64(digest);
             encPass = new String(b64);
             encPass = encPass.replaceAll("=", "");
         }catch(Exception ex){
             logger.error("An exception trying to encode a password", ex);
         }
         return encPass;
     }

     @Override
     public boolean matches(CharSequence charSequence, String s) {
         return encode(charSequence).equals(s);
     }
}

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}


@Service
public class UserDetailSecurityService implements UserDetailsService{

    //Here your user service implementation
    @Autowired
    UserService userService;

    //yuou need to oeverride this method name
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // you need to create a method in your service to find users by name
        return userService.findByUsername(username);
    }
}

In this case if you need to change to a new encoder method you only need to implement a new class with the proper system and would be done

Sign up to request clarification or add additional context in comments.

7 Comments

How did you do your class UserDetailSecurityService?
@tina added the 2 classes
I'm trying to understand why what I did didn't work. You wrote a class userservice (that surely use an userdao class) that do what the method configAuthentication do in my class. So why if I use a decode function in my sql is working in my db but not in the project? Why you have to use a method that encode and decode the password out of the sql query?
@tina usually the sql doesn't have the same options to decode/encode passwords, actually i am not sure if is even possible. Thats why you need to add the decoder in your Java class
@tina for me is easier if you dont mix DB and authentication, for instance if you want to add some Test to verify your decode system works, with your code you always would need the DB access so is not isolated. But let me check what could be wrong in your example
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.