Spring Security 복습
Spring Security란?
- Spring MVC 기반 애플리케이션의 인증(Authentication)과 인가(Authorization or 권한 부여) 기능을 지원하는 보안 프레임워크
( Spring MVC 기반 애플리케이션에 보안을 적용하기위한 사실상의 표준 ) - 특정 보안 요구 사항을 만족시키기 위한 코드의 커스터마이징이 용이하고 유연한 확장이 가능
Spring Security로 할 수 있는 보안 강화 기능
- 다양한 유형(폼 로그인 인증, 토큰 기반 인증, OAuth 2 기반 인증, LDAP 인증)의 사용자 인증 기능 적용
- 애플리케이션 사용자의 역할(Role)에 따른 권한 레벨 적용
- 애플리케이션에서 제공하는 리소스에 대한 접근 제어
- 민감한 정보에 대한 데이터 암호화
- SSL 적용
- 일반적으로 알려진 웹 보안 공격 차단
✔️ Principal (주체)
- 인증 프로세스가 성공적으로 수행된 사용자의 계정 정보
Ex. 애플리케이션에서 작업을 수행할 수 있는 사용자, 디바이스 또는 시스템 등
✔️ Authentication (인증)
- 애플리케이션을 사용하는 사용자가 본인이 맞음을 증명하는 절차
➜ 이를 위해 Credential(신원 증명 정보)이 필요
Authorization (인가 또는 권한 부여)
- Authentication(인증)이 정상적으로 수행된 사용자에게 하나 이상의 권한(authority)을 부여하여 특정 애플리케이션의 특정 리소스에 접근할 수 있게 허가하는 과정
Ex. 비행기 좌석 / 극장 티켓별 좌석 등 - 반드시 Authentication 과정 이후 수행되어야 함
- 권한은 보통 역할(Role) 형태로 부여
➜ URL에 접근할 권한이 있는지 확인
Ex. 관리자 / 사용자
Access Control (접근 제어)
- 사용자가 애플리케이션의 리소스에 접근하는 행위를 제어하는 것
이번에는 SSR(Server Side Rendering) 방식으로 구현된 Hello Spring Security 샘플 애플리케이션을 이용하여 실습을 진행합니다.
⠀
Spring Security의 기본 구조와 동작 방식을 이해하기 가장 쉬운 방식이 바로 서버에서 HTML을 만들어 클라이언트 쪽으로 내려주는 SSR(Server Side Rendering) 방식이기 때문입니다.
⠀
실습에서는 Spring Security를 적용해 모든 사용자들이 접근 가능한 화면이 되도록 설정할 수 있기만 하면되기 때문에 구체적인 컨텐츠가 없을 수 있습니다.
⠀
SSR(Server Side Rendering) 방식이란?
➜ 세션 기반의 폼 로그인 방식을 적용하기 가장 적합한 애플리케이션
⠀
폼 로그인 방식이란?
➜ Spring Security에 처음 입문하는 입문자들이 Spring Security를 이해하기에 가장 적합한 인증 방식
이전 실습까지 애플리케이션 내에 적용되지 않았던 것
- 로그인 기능(인증, Authentication)이 없음
➜ 다른 사람이 애플리케이션의 API를 호출해서 얼마든지 정보 조회 가능 - API에 대한 권한 부여(인가, Authorization) 기능이 없음
➜ 손님이 마음대로 커피 정보를 등록 가능 - 웹 보안 취약점에 대한 대비가 전혀 이루어지지 않았음
➜ 웹 애플리케이션을 위협하는 세션 고정 공격, 클릭재킹 공격, CSRF 등의 보안 취약점에 대한 고려가 전혀 이루어지지 않은 상태
Spring Security 적용
- build.gradel 파일에 아래의 의존 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
이를 추가하기 전엔 실습 내용을 실행하고 localhost:8080에 접속했을 때 누구나 접속이 가능한 밋밋한 화면이었는데,
추가한 후에는 Spring Security의 자동 구성을 통해 디폴트 로그인 페이지가 만들어져 그 화면에서 로그인을 해야만 페이지에 들어갈 수 있도록 합니다.
아이디는 user이고 비밀번호는 인텔리제이에 적혀있습니다.
하지만
이 방식은 매번 비밀번호가 바뀌기 때문에 실무에서 사용하기 어렵습니다.
데이터베이스 연동을 통한 로그인 인증
- InMemory 방식은 애플리케이션을 다시 시작하면 정보가 모두 사라지기 때문에 회원 정보를 데이터베이스 테이블에서 관리
- 여러 방법이 존재하지만 그 중 하나인 Custom UserDetailsService 를 이용할 예정입니다.
- SecurityConfigurationV2 클래스 추가
SecurityConfigurationV1에서 Memory에 직접 저장하는 userDetailsService() 메서드 제거 - JavaConfigurationV2 클래스 추가
데이터베이스에 User의 정보를 저장하기 위해 MemberService 인터페이스의 구현 클래스를 DBMemberService로 변경 - DBMemberServiceV2 클래스 추가
DBMemberServiceV1 + 회원 가입 시, User 의 권한 정보(Role)를 데이터베이스에 저장하는 코드 - HelloUserDetailsServiceV1 클래스 추가
데이터베이스에서 조회한 User 의 인증 정보를 기반으로 인증을 처리하는 Custom UserDetailsService
⠀
InMemory User 등록하는데 사용했던 InMemoryUserDetailsManager는 UserDetailsManager 인터페이스의 구현체이고,
UserDetailsManager는 UserDetailsService를 상속하는 확장 인터페이스입니다.
데이터베이스에서 User 의 인증 정보만 Spring Security 에게 넘겨주고, 인증 처리는 Spring Security가 대신해줍니다.
- HelloAuthorityUtils 클래스 추가
➜ HelloUserDetailsService에서 Role 기반의 User 권한을 생성하기 위해 사용 - application.yml 파일에 관리자 이메일 주소 정의
-> 여기까지 완료하면 DB에 패스워드가 암호화 되어 들어갑니다.
- HelloUserDetailsServiceV2 클래스 추가
( HelloUserDetailsServiceV1 의 몇 부분 개선 ) - User의 Role을 DB에서 관리하기8-2. DBMemberServiceV2 클래스에 코드 추가
회원 등록 시, 회원의 권한 정보를 데이터베이스에 저장하는 코드 추가 - 8-3. HelloAuthorityUtils 클래스에 코드 추가
DB 저장용 createRoles() 메서드 추가 - 8-1. Member 엔티티 클래스에 User 권한 정보 매핑
@ElementCollection 애너테이션 추가하여 따로 엔티티 클래스 만들지 않고 매핑 - 로그인 인증 시, User의 권한 정보를 데이터베이스에서 조회하는 작업9-2. HelloAuthorityUtils 클래스에 코드 추가
데이터베이스에서 조회한 Role 정보 기반으로 User 의 권한 목록 생성하는 createAuthorities(List<String> roles) 메서드 추가 - HelloUserDetailsServiceV3 클래스 추가
데이터베이스의 MEMBER_ROLES 테이블에서 조회한 Role 기반으로
User 의 권한 목록(List<GrantedAuthority>)을 생성하는 로직 추가
-> 여기까지 완료하면 회원가입과 로그인이 완료됩니다.
Custom AuthenticationProvider 사용하는 방법
- Spring Security 가 로그인 인증을 대신 해주지만 흐름의 이해를 위해 직접 만드는 인증 처리 로직
HelloUserAuthenticationProvider 클래스 추가
- AuthenticationProvider 인터페이스의 구현 클래스
⠀ - AuthenticationProvider - Spring Security 에서 클라이언트로부터 전달받은 인증 정보를 바탕으로 인증된 사용자인지에 대한 인증 처리를 수행하는 Spring Security 컴포넌트