티스토리 뷰

Spring

Spring Security - JPA 연동하기

엔꾸꾸 2019. 9. 8. 16:46

Spring Security - JPA 연동하기

  • InMemoryUser 방식은 문제점이 존재하기때문에 DATABASE와 연동하는 방법을 사용한다.
  • 방법이 다양하지만 그중에서도 JPA와 연동하는 방법을 사용한다.

의존성 추가하기

  • JPA 의존성을 추가하고, DATABASE는 h2 를 사용하도록 한다.

Account

  • User 정보에 해당하는 Account Entity 를 생성한다.
  • username은 유일한 값이기 때문에 Unique 제약조건을 걸어준다.

  • JpaRepository 를 상속받는 AccountRepository 를 생성해준다.
  • 기본적인 CRUD, Paging 관련 구현이 모두 끝난다.
  • 또한 추가적으로 username으로 조회를 해야하기때문에 username으로 조회하는 namedQuery Method를 정의해준다.

UserDetailsService

  • Spring Security 에서 User 정보를 Database와 연동하여 가져오는 역할을 담당하는 인터페이스 이다.

  • 이에 대한 구현체는 NoSQL, RDBMS 등 어떤 방식으로 구현을 하던 제약사항이 없다.

  • 그저 Username에 해당하는 User를 조회해 UserDetails Type으로 리턴해주는 역할만 한다.

  • 객체지향 원칙중 하나인 단일 책임의 원칙에 의하면 하나의 역할만 하는것이 맞지만 UserDetailsService의 역할도 AccountService의 역할중 하나 이기때문에 UserDetailsService의 구현체로 사용한다.

  • loadUserByUsername(String username) 의 구현

    • username에 해당하는 유저정보를 DB로 부터 읽어온다.
    • 해당하는 유저가없다면 UsernameNotFoundException 예외를 발생시킨다.
    • 존재한다면 UserDetails 를 구현하는 User Type으로 Return 해준다
      • 이전에는 User라는 클래스를 제공해 주지않아 이를 연결해주는 Adapter 클래스를 많이 사용하였다.
      • 하지만 상황에따라 Adapter 클래스를 사용할때도 존재한다.

SecurityConfig

  • 기존의 InMemory 설정은 더이상 필요가 없어졌기때문에 해당 설정은 다음과 같이 제거해준다.

문제점

  • 현재는 애플리케이션을 실행하고나면 User를 생성할 방법이 없다.
  • 따라서 편의상 Account를 생성할수 있도록 AccountController클래스를 생성해야한다.

AccountController

  • PathVariable로 role/username/password를 받아 유저를 생성하고, 생성된 유저를 반환해주는 RestController를 구현한다.
  • 하지만 이 방법은 절대 사용해선 안된다.
  • 편의상 구현한 방법이지 절대 사용해선 안되는 방법이다.

또 다른 문제점

  • 유저를 생성할수 있도록 AccountController를 생성해주었는데 무엇이 문제일까 ?
  • 바로 Account를 생성하는 url인 /account/** 에 접근하지 못한다.
  • Security 설정에 의해 현재 상태에서는 인증을 할수 없기때문...

다음과 같이 SecurityConfig에서 /account/** 를 허용해준다.

유저 생성해보기

생성된 유저로 접근하기

위와 같이 생성된 유저정보를 활용하여 접근을 해보도록 하자

  • /dashboard 로 접근하면 시큐리티 기본 로그인폼이 나타나고, user/1234로 로그인을 시도하면 로그인이 되지않는다.
  • 다음과 같은 예외가 발생한다.
    • 이전에서 설명한 {noop}1234 형식의 패스워드가 아니기때문에 발생한 문제이다.

해결방법

  • 먼저 AccountController의 코드를 수정한다.

  • 패스워드를 인코딩하는등의 로직은 Service 계층에 있는것이 맞기때문에 AccountService로 의존성을 교체해준다.

  • 또한 AccountService의 createAccount Method로 유저를 생성하도록 변경한다.

  • AccountController

  • AccountService의 createAccount Method이다.
  • 생성할 Account 를 받아 password Encoding을 진행한다.
    • {noop}1234 의 형식
  • AccountService

  • 정상적인 passwordEncoder 를 사용한 방법은 아니지만 패스워드를 평문으로 저장하기때문에 굳이 passwordEncoder를 사용하지않고,

  • Security에서 인식하도록 형식만 맞춰주도록 구현한다.

  • passwordEncoding 로직은 Service 계층에 존재할수도 있지만. Account Domain과 관련된 로직이기 때문에 Account Entity 클래스에 정의해 주었다.

  • Account

  • 애플리케이션 을 재기동 하고, 유저를 생성한뒤 /dashboard로 접근 해보자.
    다음과 같이 유저가 생성되며, 정상적으로 /dashboard로 접근이 가능해진다.

SecurityConfig 살펴보기

  • 우리는 UserDetailsService의 구현체인 AccountService를 구현했지만 이를 Spring Security에 설정하지 않았는데도 AccountService를 사용하고있다.

  • 다음과 같이 명시적으로 UserDetailsService를 사용하라고 명시해 주어야 한다.

  • 하지만 UserDetailsService 타입의 Bean이 등록되어 있다면 이런 과정을 생략할 수 있다.

  • 자동적으로 userDetailsService로 설정한다.

'Spring' 카테고리의 다른 글

Spring Security - Security Test 1  (0) 2019.09.09
Spring Security - PasswordEncoder  (0) 2019.09.08
Spring Security - InMemoryUser  (3) 2019.09.08
Spring Security - Security Config  (0) 2019.09.07
Spring Security - Security 적용하기  (0) 2019.09.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함