Java/spring

spring security를 알아보자 - 4

티코딩 2024. 3. 18. 19:35

여태까진 application.properties 에서 한명의 유저만 설정했기때문에 추가적인 유저를 만들수 있게 향상해야한다.

애플리케이션 메모리안에 다수의 유저를만들게 해보자.

 

ㅇ 인메모리상 유저를 생성하자

웹애플리케이션 메모리 내에 유저를 생성하자.

**이방법은 깃헙으로 볼수있기때문에 안전한 방법은 아님.

ProjectSecurityConfig에 

@Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails admin = User.withDefaultPasswordEncoder()
                .username("admin")
                .password("12345")
                .authorities("admin")
                .build();
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("12345")
                .authorities("read")
                .build();
        return new InMemoryUserDetailsManager(admin, user);
    }

이렇게 추가해주면, admin 계정하나와 read 읽기전용 계정하나를 만들 수 있다.

하지만 지금은 withDefaultPasswordEncoder() 메서드가 사용중단되어서 사용할 수 없다.

 

다음방법을 알아보자.

**이 방법도 프로덕션 환경에 적합하지않음. (인메모리에 저장하기 때문)

User클래스를 사용해 UserDetails를 생성할때 PasswordEncoder와 관련된 메서드를 호출하지 않는다.

대신 PasswordEncoder라는 메서드를 만들어 NoOpPasswordEncoder유형의 객체를 Bean으로 반환한다.

@Bean
    public InMemoryUserDetailsManager userDetailsService() {
        //방법2
        UserDetails admin = User.withUsername("admin")
                .password("12345")
                .authorities("admin")
                .build();
        UserDetails user = User.withUsername("user")
                .password("12345")
                .authorities("read")
                .build();
        return new InMemoryUserDetailsManager(admin, user);
    }
@Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

이번엔 withUsername() 메서드를 사용한다. 그리고 위에서설명했듯이

NoOpPasswordEncoder유형의 객체를 Bean으로 반환하는데 현재는 NoOpPasswordEncoder가 사용중지되었다.

이걸사용하면 비밀번호를 일반 텍스트로 처리하므로 보안이 굉장히 허술하기 때문이다.

 

이런 인메모리에 유저를 생성하는것은 좋지않은 방법이고, 이미 deprecated되어 사용도 불가능하다.

 

ㅇ 이번엔 UserDetailsManager, UserDetailsService가 무슨역할을하는지 알아보자.

가장위에있는 인터페이스는 UserDetailsService다. 여기엔 위에서 썼던 loadUserByUsername이란 추상메서드가 존재한다. 

이걸로 엔드유저의 정보를 가져온다.

그 다음 인터페이스는 UserDetailsManager이다. 이 인터페이스는 유저정보를 관리하는 역할을한다. 생성,수정,삭제,비밀번호수정 등의 역할을 한다. 

이 UserDetailsManager를 디테일하게 구현한 InMemoryUserDeatilsManager, JdbcUserDetailsManager 등이 있다.

자체 보안 로직을 사용하고 싶은경우, Authentication Provider를 직접 구현하면 된다. 

 

 

ㅇ UserDetails 와 User 의 구현

UserDetails 인터페이스와 구현체를 사용하면 유저의 자격증명정보를 잘 표현할 수있게된다.

UserDetails는 이런 추상메서드들을 포함하고있다. SpringSecurity팀은 샘플코드를 제공해준다.

User 인터페이스에 이게 있다. 

UserDetails,User 에는 getter메서드만존재하고 setter메서드는 존재하지 않다. 읽기만 가능하다는뜻.

UserDetails,User는 유저의 세부정보를 가져오는데 사용된다. 이렇게 가져온 정보는 Authentication Providers로 전달되고, Authentication Providers는 이 정보를 authentication 객체로 변환한다. 

 

다른 인증구현방법중 하나는 UsernamePasswordAuthenticationToken이다.

Principal은 엔티티의이름이나 로그인ID를 나타낸다.

 

이제 유저의 세부정보를 불러오려는 InMemoryUserDetailsManager를 보면 반환타입이 UserDetails이다.

그다음으로 유저를 인증하려고하는 DaoAuthenticationProvider 를 보면 반환타입이 Authentication이다.

 

정리하자면 UserDetails는 사용자의 정보를 나타내고 데이터베이스나 다른 곳에서 사용자의 정보를 가져오는 데 사용되며, Authentication은 현재 사용자의 인증 상태를 나타내고 이 정보를 기반으로 사용자에게 접근 권한을 부여한다.