지금까지 우리는
성공적으로 MySQL 데이터베이스를 구축하였으며
이 데이터베이스 내부에는
Spring Security에서 제시하는 표준대로
표와 열을 생성하여
JdbcUserDetailsManager를
인증에 사용할 수 있도록 하였습니다
보시듯이 여기 users 표와
authorities 표가 있습니다
users 표에는 로그인 아이디와 비밀번호가 있으며
동시에 authorities에는
제 유저가 가지고 있는 인증 정보가 있습니다
아직 역할과 인증에 대한 사항은
다루지 않았습니다
지금으로서는 JdbcUserDetailsManager를 활용하여
데이터베이스에 저장된 자격 증명으로
로그인이 정상적으로 되는지를 확인하려고 합니다
또한 지금 자격 증명 정보는
이렇게 일반 텍스트로 입력 되어 있습니다
이는 권장되지 않는 방식이므로
이 웹 애플리케이션을 우리는 개선하여
Spring Security에 있는
비밀번호 인코딩을 이용하여
비밀번호를 해싱과 암호화를 거친 형태로 저장할 겁니다
그 전에 JdbcUserDetailsManager를
활용하기 위해서는
웹 애플리케이션에 변경해야 할 것들이 있습니다
pom.xml 내부에서 가장 먼저 하고 싶은 것은
아래로 스크롤해서 ldap dependency 아래에
세 개의 dependencies를 새로 추가하는 것입니다
이 세 개의 dependencies를 하이라이트해 놓고
이것들에 대해 이야기해 봅시다
첫 번째 dependeny는 spring-boot-starter-jdbc입니다
먼저 이 dependency를 추가하여야 합니다
우리는 Jdbc 프레임워크를 활용하고 있기에
데이터베이스에서 기록을 반환하기 위해서는
이 dependency를 추가하여야 합니다
두 번째 dependency는 MySQL에 연관되어 있습니다
MySQL 데이터베이스를 사용하고 있으므로
pom.xml에 mysql-connector-j dependency를
추가해 주어야 합니다
그리고 추가할 마지막 dependency은
spring-boot-starter-data-jpa입니다
이 dependency를 왜 추가했냐면 나중 강의에서
Spring Boot 데이터 JPA 프레임워크를
데이터베이스에서 기록을 반환하거나
데이터베이스 관련 트랜잭션을 하는 데
활용할 것이기 때문입니다
그래서 지금 이 dependency를 미리 추가하는 겁니다
이 dependencies들은 GitHub 리포지터리에도 있습니다
그러므로 리포지터리에서 복사해서
여러분의 pom.xml에 붙여넣으면 됩니다
이 dependencies들을 언급하고 pom.xml을 저장하였으면
이제 Maven 변경사항을 불러와야 합니다
그러니 Refresh 버튼을 클릭하겠습니다
그러면 이 세 dependencies에 관련된
JavaScript가 다운로드될 겁니다
두 번째로 변경할 것은
application.properties 내부에 있습니다
지금은 비어 있습니다
그러므로 여기에 우리는
MySQL 데이터베이스의 자격 증명을 제공하여
Spring Boot 웹 애플리케이션이
AWS 클라우드 안에 우리가 생성한
MySQL 데이터베이스에 연결할 수 있도록 해야 합니다
여기에 프로퍼티 몇 개를 입력하겠습니다
여기에 보이듯이
첫 번째는 spring.datasource.url입니다
이 내부에 무엇을 제공해야 하냐면
jdbc:mysql://이라 입력한 다음
제 데이터베이스의 호스트명
그 다음에는 MySQL에서 생성한
데이터베이스가 무엇인지
입력해야 합니다
생성했던 데이터베이스의 이름은
eazybank이었습니다
그러므로 여기 똑같이 입력해 주고
username은 admin
password는 MySQLSpringSecurity였습니다
이 두 프로퍼티가
제 콘솔에서 데이터베이스에 대하여
실행되고 있는 SQL을 출력하도록 도울 겁니다
가장 처음 하이라이트되어 있는 프로퍼티는
콘솔에 있는 모든 SQL을 표시할 것이며
두 번째는
이해할 수 있는 포맷으로
SQL 검색이 표시되도록 도울 겁니다
이러지 않으면 콘솔에 표시되는 SQL 검색은
모두 한 줄로 출력되기 때문에
읽을 수가 없습니다
반면에 format_SQL=true를 사용한다면
SQL이 모두 알맞게 포맷되고
읽을 수 있는 형태로
콘솔에 표시되거나 출력될 것입니다
그러므로 데이터베이스 호스트명
자격 증명 그리고 데이터베이스 이름을
제가 한 것처럼 언급하도록 해 주십시오
그리고 물론 실제 상황에서는 당연히 데이터베이스 자격 증명을
직접 언급하는 것은 권장되지 않습니다
DevOps(개발운영)팀은 항상
이 자격 증명을
CI/CD 파이프라인 또는 Jenkins와 같은 개발 툴을 이용하여
환경 변수로 주입하려고 할 겁니다
하지만 우리는 개발자이며
지금은 Spring Security를 배우려 하고 있을 뿐이니
자격 증명을 직접 입력해도 됩니다
그러나 실제 웹 애플리케이션에서는
절대로 자격 증명을 직접 입력하면 안 됩니다
항상 DevOps(개발운영) 팀의 도움을 받으십시오
이제 자격 증명을 정의하였으면
ProjectSecurityConfig로 가겠습니다
여기서 해야 할 일은
InMemoryUserDetailsManager와 연관된
모든 코드를 주석으로 바꾸는 것입니다
이제 더 이상
InMemory 방식의 인증을 사용하지 않기 때문입니다
이제는 Jdbc 인증 방식을 사용하여
데이터베이스에 기록과 유저 정보를 저장하려 합니다
그러므로 InMemoryUserDetailsManager에 관련된
모든 코드는 주석으로 변경하겠습니다
참고할 수 있도록 남겨만 두는 겁니다
주석으로 바꾸었으면
이제 해야 하는 일은
JdbcUserDetailsManager 타입의 Bean을 하나 더 만드는 겁니다
새로 생성하고 싶은 Bean은
JdbcUserDetailsManager라고 입력합니다
방금 ProjectSecurityConfig에
새로운 메소드를 추가하였습니다
메소드의 이름은 UserDetailsService로 같습니다
그리고 이 메소드에는 DataSource 객체를 보내려 합니다
이러면 MySQL 관련 디펜던시를
클래스 경로에 추가하고 데이터베이스의 프로퍼티를
application.properties에서 정의할 때마다
Spring Boot는 데이터 소스 객체를 자동적으로
웹 애플리케이션 내부에 생성할 것입니다
즉 이 DataSource 객체가
JdbcUserDetailsManager에게 넘어갈 때마다 말입니다
그래서 JdbcUserDetailsManager에게
저는 데이터베이스를 생성하였으며 그에 대한 정보는
이 데이터 소스에 있다고 알려주는 것입니다
그게 JdbcUserDetailsManager
객체가 생성되는 이유입니다
여기에 나와 있듯이
데이터 소스 정보를 넘기도록 유의하여야 합니다
그리고 이 메소드의 반환 타입은
InMemoryUserDetailsManager에서 그랬듯이
JdbcUserDetailsManager로 하거나
UserDetailService를 언급한다면
문제는 없을 것입니다
왜냐하면 이 인터페이스 UserDetailService는
이 클래스의 부모 클래스이기 때문입니다
그러므로 프로그램은 순순히 작동할 겁니다
지금 저는 Bean을 생성할 때
메소드 반환 타입을
넘기는 다른 방법을 보여드리기 위해
UserDetailService를 사용하고 있습니다
그리고 마지막으로 Bean이라는 것을 나타내 줍니다
이제 성공적으로
JdbcUserDetailsManager 타입의 Bean이 생성되었습니다
이걸로 제 Spring Security는 이 친구가
Jdbc 인증 방식을 사용하려 한다는 것을
이해할 수 있으며 데이터베이스 정보를 가지고 있어
데이터베이스에 가서 검색을 실행할 수 있습니다
그것을 기반으로 인증을 시도할 것입니다
그럼 여기에 질문이 있습니다
이 PasswordEncoder Bean은 필요할까요?
당연히 필요합니다
이유는 Spring Security에게는 항상
비밀번호를 어떻게 저장하였는지 알려주어야 하기 때문입니다
일반 텍스트로 저장되었는지
아니면 암호화와 해싱을 이용하여
저장되었는지 말입니다
그러므로 PasswordEncoder Bean은
항상 필요합니다
여기 작성된 Bean은
Spring Security 프레임워크에
NoOpPasswordEncoder라고 알려주도록 되어 있습니다
“지금 제 비밀번호들은 일반 텍스트로 되어 있으니
인증을 실행할 때에도
일반 텍스트로 취급하여 주십시오”
코드를 통해 프레임워크에게 하고자 하는 말입니다
이걸로 충분할 겁니다
여기서 모든 변경 사항을 포함한 완전한 빌드를 진행하겠습니다
이제 main 클래스로 가서 debug을 선택하여
웹 애플리케이션을 시작할 수 있습니다
하지만 웹 애플리케이션을 실행하기 전에
여러분의 데이터베이스가 있는 곳
로컬 또는 클라우드로 가서
데이터베이스가 작동하고 있는지 확인하고 와 주십시오
제 서버는 8080번 포트에서 실행되었습니다
이제 브라우저의 개인정보 보호 모드를 이용하여
데이터베이스에 저장되어 있는
자격 증명이 정상적으로 기능하는지 확인하겠습니다
새로운 브라우저 창을 열었습니다
보안된 REST API 경로인
MyAccount 경로에 접근을 시도하겠습니다
접근을 시도하자마자
자격 증명을 요구합니다
이전 강의에서 Spring Boot 웹 애플리케이션의
InMemory에 설정해 놓았던
아이디와 비밀번호로 시도하여 봅시다
admin, 12345입니다
InMemory 인증 방식을 사용하고 있지 않기 때문에
통하지 않습니다
지금 우리가 사용하는 인증 방식은 Jdbc입니다
JdbcUserDetailsManager 클래스 내부에
중단점를 두겠습니다
JdbcUserDetailsManager를 열겠습니다
그러면 여기에는 호출할 메소드들이 나와 있습니다
메소드 이름은 LoadUserByUsername입니다
이게 클래스가 호출할 메소드입니다
이 메소드는 이 클래스 내부의
또 다른 메소드를 호출할 것인데
그 메소드의 이름은 LoadUsersByUsername입니다
제가 할 것은 이 메소드 내부에
중단점을 두어서
저의 Spring Security가 정말로
JdbcUserDetailsManager와 JdbcDaolmpl 내부의 코드를
활용하고 있는 것인지 확인하는 것입니다
이 메소드는 JdbcDaolmpl에 존재하며
JdbcUserDetailsManager에서도 이를 활용합니다
그러므로 이 클래스 역시 같은 메소드를 지닌 것과 마찬가지입니다
다른 클래스에 왜 이 메소드가 있는 건지
혼란스러워 할 필요 없습니다
이제 브라우저로 가서
자격 증명을 입력합니다
자격 증명은 아이디는 happy
비밀번호는 12345입니다
자격 증명에 happy를 입력하면
우리 인생도 happy해질 수 있을지 봅시다
Username은 happy, Password는 12345입니다
그 다음 Sign in 버튼을 클릭합니다
아까 브레이크포인트에 아이디가 happy이면
실행을 중지하라고 입력했습니다
이로 Spring Security가 프레임워크 내부의
JdbcUserDetailsManager를 활용한다는 것이 확인되었습니다
이 중단점을 삭제하겠습니다
이제 브라우저로 가서
인증이 성공적이었는지 확인합시다
성공적으로 응답을 받았습니다
모든 것이 우리 예상대로
정상 작동하고 있다는 뜻입니다
우리가 지금 무엇을 하고자 하는지
이해가 되시면 좋겠습니다
데이터베이스 인증의 장점은
아무리 많은 기록과
아무리 많은 유저를
등록하여도 보안이 잘 된다는 것입니다
실제 애플리케이션에서도 같은 방법을 사용합니다
물론 실제로는 비밀번호를
일반 텍스트 형태로 저장하지는 않지만 말입니다
애플리케이션은 해시된 비밀번호를 암호화하여
데이터베이스에 저장할 것입니다
그러므로 우리도 웹 애플리케이션을 향상하여
비밀번호를 데이터베이스 내부에
암호화된 형식으로 저장하여
아무도 실제 비밀번호를 알 수 없도록 할 것입니다
이것으로 여러분이
JdbcUserDetailsManager의 도움으로
무엇을 할 수 있는지 이해가 되셨으리라 믿습니다
감사드리며 다음 강의에서 뵙겠습니다