Spring Security
Spring Security
백기선님의 강의인 Springboot 개념과 활용 강의를 듣고 공부한 내용을 정리한 글
Spring Security
Spring Security는 기본적으로 인증에 관련된 기능들을 제공해준다.
모든 요청이 Spring Security에 의해 인증을 요구한다.
Basic 인증과 폼 인증이 모두 적용된다.
Basic 인증은 Accept-Header에 따라 달라진다.
Basic 응답을 받으면 브라우저는 기본적으로 로그인 폼을 띄우게 된다.
따라서 루트에 접근하더라도 인증정보가 없기 때문에 /login
으로 리다이렉션을 하게 되고, 꾸며지지 않은 로그인 폼을 만나게 된다.
이 또한 스프링부트의 자동설정에 의해 만들어진 정보이다.
스프링 부트 시큐리티는 뭔가 하는 척 하지만 사실 아무 기능이 없으며 스프링 시큐리티의 설정을 그대로 사용한다.
그래서 스프링 부트에서 지원하는 시큐리티는 거의 쓸 일이 없다.
커스터마이징
Spring Security에서 가장 핵심적인 메소드는 configure이다.
여기서 모든 리퀘스트에 인증 요청을 요구하며
폼 인증과 httpBasic 인증을 사용하고 있다.
만약 특정 페이지는 모든 유저가 접근이 가능하고
특정 페이지 외에 모든 페이지들은 인증을 해야만 접근할 수 있게 하려면 어떻게 해야할까?
이때는 WebSecurityConfigureAdapter를 상속받아 구현하고 빈으로 등록하면 된다.
이때 WebSecurityConfigureAdapter를 상속받은 클래스가 빈으로 등록되면 Springboot에서 제공하는 SecurityAutoConfiguration이 더이상 작동하지 않고 우리가 새로 정의한 Configuration이 적용된다.
그런데 로그인할 때 UserDetailsService
로 인해 스프링부트에서 자동으로 만들어지는 계정으로만 로그인이 가능하다.
일반적으로 DB와 연동된 유저의 로그인 처리를 하고 싶은 경우에는 UserDetailsService
를 구현하고 커스터마이징 하여 사용할 수 있다.
그러면 더이상 스프링부트에서 제공하는 기본 유저를 생성하지 않고 DB와 연동된 유저를 검증한다.
검증을 담당하는 객체는 UserDetails
이며 사용자가 입력한 계정 ID와 비밀번호가 DB의 아이디 비밀번호와 일치하는지 검증한다.
그러나 DB에 계정을 추가하고 로그인을 하여도 id가 null
이라는 에러를 뱉는다.
이때 대략 정신이 혼미해지지만 정신차리고 왜 그런지 이유를 알아보자.
기본적으로 PasswordEncoder
의 역할은 DB에 저장되는 비밀번호를 인코딩하여 저장하는 것을 도와주는 객체이다.
현재 AccountService
에서는 PasswordEncoder
없이 DB에 유저를 저장하고 있는 것을 볼 수 있다.
Spring Security 버전이 올라가면서 {noop}password
형태여야만 디코딩을 시도한다.
지금처럼 아무것도 없는 상황에서는 에러를 발생시킨다.
NoOpPasswordEncorder 클래스를 빈으로 등록하면 비밀번호의 어떠한 인코딩을 하지 않더라도 로그인을 하게 해준다.
그러나 이는 절대
추천하지 않는 방법이며 스프링 시큐리티에서 권장하는 인코더를 사용하여야한다.
스프링 시큐리티에서 권장하는 DelegationPasswordEncoder를 빈으로 등록하고,
PasswordEncorder를 의존성 주입을 받아 비밀번호를 인코딩 해주면 된다.
비밀번호를 출력해보면 bcrypt
라는 방식으로 인코딩이 되었다는 것을 알 수 있다.
Reference
인프런 백기선님의 스프링 부트 개념과 활용