简体   繁体   中英

Bypass PasswordEncoder in Spring Security for already encrypted passwords

I have a REST Spring Boot 2 application. For this application I'm trying to implement a security mechanism which would accept login requests with both raw and encrypted passwords.

For the raw passwords the application works fine. I can create users, store their encrypted passwords in the database and authenticate them when they send the raw password.

The thing is that there are situations where we have client services with pre-configured users with their already encryted passwords, and they need to send this encrypted password for authentication.

My configuration is currently as follows:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

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

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new PasswordEncoder() {

            final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10, new SecureRandom());

            @Override public String encode(CharSequence rawPassword) {
                return encoder.encode(rawPassword);
            }

            @Override public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encoder.matches(rawPassword, encodedPassword);
            }
        };
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();

        http.headers()
                .frameOptions()
                .sameOrigin();
        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

Is there a way to somehow bypass the PasswordEncoder? Because in some cases there is already an encrypted password and maybe all we would need is to compare it with the existing stored encrypted one.

Also, would that be an anti-pattern? Any tips are appreciated.

If you don't know if the password is encoded or not you can try this but it need to be hashed with the same algo.

   @Override public boolean matches(CharSequence rawPassword, String encodedPassword) {
            if(encodedPassword.equals(rawPassword.toString())
                 return true;

            return encoder.matches(rawPassword, encodedPassword);
        }

You could create a noop implementation of password enconder:

**NoOpPasswordEncoder.getInstance()** 

And to handle encoded/raw passwords you could implement your own:

**AuthenticationEntryPoint**

In which you could implement your logic based on some kind of header? Which you could use like that in your Spring Security config

http.cors().and().exceptionHandling().authenticationEntryPoint(<yourEntryPoint>)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM