[Spring Security] Hello Spring Security -2

·2022년 11월 25일
0

SpringSecurity

목록 보기
7/13
post-thumbnail

Hello Spring Security 1
이전 학습 내용에 이어서 데이버베이스에 연동된 로그인 인증 프로세스를 구현!

로그인을 위해서라면 필수적으로 필요한 기능은 회원가입 기능이다. Hello Spring Security 1에서 학습한 내용만으로 애플리케이션을 실행하면 당연하게도 회원가입 후 로그인을 시도하면 인증에 실패한다.

당연함.

회원가입을 진행한 사용자의 정보가 그 어디에도 저장되어 있지 않아 Spring Security는 지금 매우 어리둥절한 상태임

Spring Security : 가입도 안한 놈이 로그인을 해잇!🤔

데이터베이스 연동이 없는 로그인 인증

Hello Spring Security 1Configuratin 클래스 내부에 UserDetailsService 메서드를 통해 User 정보를 등록했다.

여기서 InMemory User로 등록되는 것을 기억해야 한다. 별도의 데이터베이스에 User 정보를 저장하고 등록한 것이 아니라 인메모리에 등록!

🧐 InMemory 에 등록한 경우 애플리케이션의 실행이 종료되는 순간 해당 정보들은 사라져버린다. -> 테스트, 데모 환경에 사용하기 적합

회원가입 폼 만들기

1. PasswordEncoder Bean 등록

💡PasswordEncoder

Spring Security에서 제공하는 패스워드 암호화 기능을 하는 컴포넌트.

⭐ 회원 가입 폼에서 전달 받은 패스워드는 반드시 등록 전에 암호화를 해줘야 한다.

User 정보가 있는 Configuratin 클래스에 PasswordEncoder를 Bean으로 등록하였다.
PasswordEncoderFactories.createDelegatingPasswordEncoder(); 통해 DelegatingPasswordEncoder(패스워드 인코더의 대리인)를 먼저 생성한다. 이때 생성된 DelegatingPasswordEncoder가 실질적으로 PasswordEncoder의 구현 객체를 생성한다.

🧐 userDetailsService() 메서드에서 미리 생성한 InmemoryUser의 패스워드는 내부적으로 디폴트 PasswordEncoder를 통해 암호화된다.

2. JavaConfiguration 구성

JavaConfigurationMemberService Bean 등록으로 위한 클래스라는 것을 기억하자.

🧐 Service 클래스는 @Service 애너테이션을 통해 Spring Bean으로 등록하였는데 여기서는
JavaConfiguration을 이용해 Bean으로 등록하고 있다.

3. InMemoryMemberService 클래스 구현

⭐DI, UserDetailsManager와 PasswordEncoder

☝️UserDetailsManager
InMemoryMemberService는 데이터베이스 연동 없이 메모리에 Spring Security의 User 객체를 등록해야 하므로 UserDetailsManager가 필요하다.

이때 UserDetailsManager 인터페이스의 하위 클래스는 InMemoryUserDetailsManager라는 것을 잊지 말자!

🧐 UserDetails
Spring Security에서 관리하는 User 정보는 UserDetails로 관리한다!!!!!

✌️PasswordEncoder
User 등록 시, 패스워드 암호화는 필수!

🧐 SimpleGrantedAuthority를 사용해 Role 베이스 형태의 권한을 지정할 때 반드시 Role_ + 권한명 형태로 지정해야 적절한 매핑이 이루어진다.
ex.
Role_USER -> OK!
RoleUser -> NO!

데이터베이스 연동을 통한 로그인 인증

다시 말하지만 Inmemory 환경에서 사용자 정보를 메모리에 저장할 경우, 애플리케이션이 종료됨에 따라 데이터도 싹 사라져버린다. 따라서 해당 방법은 테스트 환경, 데모 환경에서나 사용하는 방법이다.

실제 서비스 환경에서는 별도의 영구적인 데이터베이스를 사용하여 사용자의 인증 정보를 관리해야 한다.

회원가입 폼 만들기

1. PasswordEncoder Bean 등록

위 내용과 동일하므로 생략!

2. JavaConfiguration 구성

위 내용과 동일하나 한가지 다른 점이 있다.

인메모리 환경에서는 UserDetailsManager를 DI 받은 것과 다르게 데이터베이스 환경에서는 Repository를 DI 받는다는 것을 기억하자!!

3. DBMemberService 클래스 구현

Service 클래스의 역할은 User의 인증 정보를 데이터베이스에 저장하는 것이다.

InMemory 환경에서는 별다른 설정없이도 내부적으로 패스워드가 암호화되어 저장된다. 그러나 DB환경에서는 PasswordEncoder암호화를 한 후, 사용자의 인증 정보에 재할당할 필요가 있다.

⭐ 패스워드는 민감한 정보이기 때문에 반드시 단방향 암호화 진행 후 DB에 저장해야 한다!

인증 처리 클래스

회원가입 폼을 완성했으니 이제 로그인을 할 때, 클라이언트가 입력한 정보가 DB에 저장되어 있는 사용자의 정보와 일치하는지, 또는 가입한 회원이 맞는지에 대한 인증이 필요하다.

인증 처리란, 데이터베이스에서 조회한 User의 인증 정보를 기반으로 인증을 처리하는 것으로
UserDetailsService 인터페이스를 구현한 Custom UserDetailsService 구현체를 구성해 사용한다.

🧐 UserDetailsService 인터페이스는 Spring Security에서 제공하는 User 정보를 Load하는 핵심 인터페이스이다.
UserDetailsManagerUserDetailsService를 상속하는 확장 인터페이스!

1. HelloUserDetailsService 클래스 구현

⭐DI, MemberRepository와 HelloAuthorityUtils

☝️MemberRepository

데이터베이스에서 User를 조회해야 한다.

✌️HelloAuthorityUtils

DB에서 조회한 User의 권한 정보를 생성하기 위한 클래스

loadUserByUsername()

Repository에서 가져온 사용자의 정보(객체)를 UserDetails로 반환한다.

🧐 UserDetails 는 UserDetailsService에 의해 로드되어 인증을 위해 사용되는 핵심 User 정보를 표현하는 인터페이스
인증 처리 흐름에서 확인할 수 있듯이 UserDetails 인터페이스의 구현체는 보안 정보 제공을 목적으로 직접적으로 사용되지 않고, Authentication 객체로 캡슐화되어 제공된다.

2. HelloUserDetails

HelloUserDetailsService 클래스의 내부 클래스로 Member 클래스를 상속 받고 UserDetails 인터페이스를 구현한 클래스이다.

loadUserByUsername()를 통해 조회한 사용자 객체를 HelloUserDetails로 보내 Spring Security의 User 정보로 변환하고, 권한 정보를 생성하는 과정을 캡슐화한다.

⭐SetRoles() 은 UserDetails에 사용자의 Role를 저장하고 있다. UserDetails 인터페이스의 getAuthorities() 메서드를 구현하여 DB에 저장된 Role 정보로 User 권한 목록을 생성한다.

3. HelloAUthorityUtils

HelloUserDetailsService 클래스에서 Role 기반의 User 권한을 생성하기 위한 클래스

3-1. 메모리 상의 Role을 기반으로 권한 정보 생성

@Value("${프로퍼티 경로}")

프로퍼티의 값을 클래스내에서 사용할 수 있도록 하는 애너테이션이다. 그럼 프로터피 값이 뭐야?

application.yml에 작성되어 있는 값을 말한다.

@Value가 추가된 필드변수의 값이 곧 프로퍼티의 값과 동일하다는 것을 의미한다.

⭐ ADMIN_ROLES, USER_ROLES

Spring Security에서 지원하는 AuthorityUtils 클래스를 이용해 관리자, 일반 사용 권한 목록List<GrantedAuthority> 객체로 생성하여 사용한다.

3-2. DB에 저장된 Role을 기반으로 권한 정보 생성

단순하게 데이터베이스에 저장된 Role 목록(List<String> roles)을 가져와 그대로 이용해 권한 목록을 만드는 방법

😵‍💫

profile
🧑‍💻백엔드 개발자, 조금씩 꾸준하게

0개의 댓글