HTTP Basic Authentication를 사용한 간단한 인증 처리

목표

spring security를 사용하여 간단한 인증 프로세스를 구현하고 구성 요소를 재정의해보자.

 

Basic Authentication이란?

 

사용자를 식별하는 방법 중에 가장 단순한 방법이다.

http 헤더에 username과 password를 넣어 인증하는 방식이다.

Authorization 헤더에 "Basic"과 "username:password"의 base64 인코딩 값을 넣어준다.

(인증과 인가에 대해 알고 있다면, basic authentication인데 왜 Authorization에 넣을까?하는 의문이 들 수 있지만, 관례에 따른 것이므로 넘어가자)

 

spring security 의존을 추가한 후 아무런 설정을 하지 않고 프로젝트를 실행하면 아래와 같이 콘솔에 암호가 추가된다.

인증 프로세스의 기본 구현체는 http basic을 포함하기 때문에 접근하기 위해서는

username 기본값인 user와 password를 사용하여 아래처럼 접근해야 한다.

curl -u user:6886fb28-c97e-472b-a327-fc7c17204b25 localhost:8080

 

혹은 브라우저로 접속하여 다음의 로그인 페이지를 볼 수 있다.

 

아래 글은 basic authentication과 관련된 간단한 실습을 포함하고 있다.

https://jujemu.tistory.com/79

 

OpenSSL을 사용해서 localhost와 https로 통신하자

OpenSSL을 사용해서 localhost와 https로 통신하자 목표 spring security의 http basic을 이해하고 localhost와 https로 통신해본다. 환경 스프링 부트 3.2.0 > Dependencies - spring-boot-starter-web - spring-boot-starter-security htt

jujemu.tistory.com

 

 


 

 

인증 프로세스

 

위 그림은 인증 프로세스의 구성 요소를 표현하고 있다.

요청을 필터가 가로채고 인증 매니저에게 위임한다.

매니저는 여러 공급자(provider) 중에 해당 요청 인증에 적합한 공급자를 선택하여 사용자를 식별한다.

각 공급자는 UserDetailService와 password encoder를 포함한다.

UserDetailService는 사용자를 식별하기 위해 필요한 UserDetails를 반환한다.

Password encoder는 암호를 암호화하거나 복호화한다.

Spring context는 인증의 결과를 저장하고, 인증의 결과를 응답할 때까지 유효하도록 한다.

 

스프링 부트는 스프링 시큐리티와 같은 의존이 추가되면 기본 설정을 추가하도록 되어있다.

이제 기본 설정을 바꾸면서 인증 프로세스를 이해해보자.

우선 UserDetailService를 갈아끼고, Password encoder를 빈에 등록하자.

 

구성요소 갈아 끼기: UserDetailService, PasswordEncoder

InMemoryUserDetailsManager는 프레임워크에서 제공하는 UserDetailService의 구현체이다.

이름에서 알 수 있듯이 메모리에 사용자 정보를 저장하고 요청에서 식별한다.

아래 코드는 마잡개라는 이름의 유저를 사용자로 등록하고 InMemoryUserDetailsManager를 빈에 등록하고 있다.

중간에 User는 package org.springframework.security.core.userdetails 에서 제공하는, UserDetails 구현체이다.

@Configuration
public class UserDetailServiceConfig {

    @Bean
    public UserDetailsService userDetailService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        UserDetails user = User.withUsername("마잡개")
                .password("1234")
                .authorities("read")
                .build();
        manager.createUser(user);
        
        return manager;
    }
}

 

참고로 UserDetailsService와 InMemoryUserDetailsManager의 관계는 위와 같다.

UserDetailsManager는 사용자를 식별하기 위한 UserDetails를 반환하는 UserDetailsService에서 아래 메서드가 추가된다.

public interface UserDetailsManager extends UserDetailsService {
    void createUser(UserDetails user);

    void updateUser(UserDetails user);

    void deleteUser(String username);

    void changePassword(String oldPassword, String newPassword);

    boolean userExists(String username);
}

 

아래에 PasswordEncoder를 빈에 등록한다.

NoOpPasswordEncoder는 별다른 암호화없이 password를 텍스트로 저장한다.

singleton으로 관리되어 static 메서드로 객체를 반환한다.

@Configuration
public class UserDetailServiceConfig {

    @Bean
    public UserDetailsService userDetailService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        UserDetails user = User.withUsername("마잡개")
                .password("1234")
                .authorities("read")
                .build();
        manager.createUser(user);

        return manager;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

 

이제 terminal에서 curl을 통해 접근하면, 200 응답을 받을 수 있다.

 

 

출처

 

Spring security in action - 위키북스

 

'스프링' 카테고리의 다른 글

[Spring Security] 스프링 시큐리티가 사용자를 이해하는 방법  (0) 2024.03.26
QueryDSL 비벼먹기  (0) 2023.10.24
QueryDSL 쪄먹기  (1) 2023.10.23
QueryDSL 볶아먹기  (0) 2023.10.22
QueryDSL 다져먹기  (0) 2023.10.21