복붙노트

[SPRING] Bcrypt로 InMemoryAuthentication 비밀번호 암호화

SPRING

Bcrypt로 InMemoryAuthentication 비밀번호 암호화

UserDetailsService의 사용자 지정 구현에서 Bcrypt를 사용하기 전에 먼저 메모리 내 데이터베이스에서 사용할 수 있는지 확인하려고합니다.

package com.patrick.Security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private UserDetailsService userDetailsService;


    @Autowired
    public WebSecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .antMatchers(HttpMethod.POST, "/users").hasAuthority("ADMIN")
                .antMatchers(HttpMethod.POST, "/shifts").hasAnyAuthority("ADMIN", "SUPERVISOR")
                .anyRequest().authenticated()
                .and()
                .addFilter(new AuthenticationFilter(authenticationManager()))
                .addFilter(new AuthorizationFilter(authenticationManager()));
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
                .withUser("admin").password("password").roles("ADMIN");
    }

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

PasswordEncoder 빈을 생성 / 노출하면이 경고가 나타나서 궁극적으로 로그인 경로에 액세스하지 못하게됩니다.

o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt

Deprecated NoOpPasswordEncoder를 추가하면 일시적으로 문제가 해결되지만 비밀번호가 암호화되지 않습니다.

@SuppressWarnings("deprecation")
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}

Bcrypt를 추가하는 올바른 방법은 무엇입니까?

해결법

  1. ==============================

    1.

    o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt
    

    이것은 사용자가 제공하는 암호가 BCrypt로 인코딩되지 않았기 때문입니다. "암호"를 암호로 직접 전달하는 대신 먼저 인코딩해야합니다.

    테스트 목적으로, 이것을하기위한 쉬운 방법은 패스워드 인코더를 잡고 이것을 다음과 같은 configure 메쏘드로 인 코드하는 것이다.

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        String password = passwordEncoder().encode("password");
        auth.inMemoryAuthentication().withUser("admin").password(password).roles("ADMIN");
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
  2. ==============================

    2.Spring Security 5를 사용하면 선택한 PasswordEncoder의 id에 password 접두어를 붙일 수 있습니다. 일반 암호를 사용하려면 {noop} 접두어 만 사용하면 암호 인코더가 NoOpPasswordEncoder에 위임됩니다.

    Spring Security 5를 사용하면 선택한 PasswordEncoder의 id에 password 접두어를 붙일 수 있습니다. 일반 암호를 사용하려면 {noop} 접두어 만 사용하면 암호 인코더가 NoOpPasswordEncoder에 위임됩니다.

    예제 코드 :

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.inMemoryAuthentication()
              .withUser("admin").password("{noop}password").roles("ADMIN");
    }
    
  3. ==============================

    3.위의 솔루션을 적용한 후에도 여전히 오류 아래에 있습니다.

    위의 솔루션을 적용한 후에도 여전히 오류 아래에 있습니다.

        @Bean
            public BCryptPasswordEncoder passwordEncoder1() {
                return new BCryptPasswordEncoder();
            }
        @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            final String password = passwordEncoder1().encode("password");
                // final String password = encoder.encode("user");
                auth.inMemoryAuthentication()
                    // .passwordEncoder(encoder)
                    .withUser("user")
                    .password(password)
                    .roles("USER");
    
    Error - 2019-04-06 15:50:35.818  WARN 16096 --- [nio-8081-exec-9] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt
    
  4. from https://stackoverflow.com/questions/49312301/encrypting-inmemoryauthentication-passwords-with-bcrypt by cc-by-sa and MIT license