-

[스프링부트 및 JPA] - Principal 넘기기 본문

백엔드 기술 정리/스프링 부트

[스프링부트 및 JPA] - Principal 넘기기

흣차 2022. 2. 15. 02:36
728x90
반응형

시큐리티는 거의 마무리가 되었습니다.

이제 해결해야할 부분은 이미지 처리와 연결, 팔로잉구현, 회원정보 수정, 게시글 올리기 등을 해보겠습니다.

ImageController를 만들겠습니다.

그런 다음

이미 프론트단은 거의 구현이 되어 있기 때문에 다음과 같이 만들어서 홈페이지와 인기페이지를 GetMapping으로 구현합니다.

마찬가지로 클래스를 하나 더 만들건데, UserController라고 짓고 회원정보페이지를 들어갈 수 있는 함수를 만듭니다.

그리고 /user/로 들어가서 회원별로 프로필을 들어갈 수 있게 /user/{id}라고 입력하면 입력되는 id값에 따라 페이지를 구분지어서 접속할 수 있습니다.

그러므로 파라미터로 가져올 때도

이런식으로 가져와야 합니다.

이렇게 파라미터를 가져오는 바인딩 방식을 '주소변수매핑'이라고 합니다.

스프링부트 및 JPA를 처음 포스팅할 때 이 블로그에도 담았던 내용입니다.

이어서 사진을 올리려고 할 때 업로드 메서드도 만들어야하는데, 다음과 같이 작성합니다.

자 지금까지 따라왔으면 우리는 하나의 세션을 가지고 있는 채로 작업을 해야한다는 것을 아셔야겠습니다.

그럼 만들어진 이 세션은 어디있을까요?

 

자 우리가 시큐리티를 통해서 로그인을 했었습니다.

그럼 사용자가 /auth/signin을 Post요청을 이용하여 로그인을 진행할 때 누가 낚아채죠?

시큐리티 Configure의 설정되어 있는 것들이 서버에 들어가기전, 서버의 앞단에서 서버를 보호하는 시큐리티가 이것을 낚아챕니다.

그리고 나서 저희가 만든 Details 타입의 PrincipalDetailsService에 이 정보를 넘기게 됩니다.

이후 PrincipalDetailsService내부에서 Username이 있는지 확인을 했었습니다.

확인을 해서 있을 때와 없을 때로 분기가 나뉩니다.

만약 유저 정보가 없으면 그냥 쫓아보내겠죠. 

하지만 있으면 '어 있구나. 그럼 니가 return한 PrincipalDetails를 세션에 저장할게' 이렇게 됩니다.

왜 PrincipalDetails일까요?

우리가 PrincipalDetailsService를 만들 때

UserDetailsService를 상속하기 때문이에요.

같은 타입이니까 바꿔치기한거랍니다.

근데 이 세션은 일반적인 세션이 아닙니다. 세션 영역을 좀 더 깊게 살펴보면 PrincipalDetails가 Key, Value형태로 있습니다.

원래는 Key이름이 Hello고 Value가 안녕이라면 Key만 찾으면 Value를 찾을 수 있습니다.

이걸 찾는 것은 굉장히 쉽습니다. HttpSession이라는 객체를 Request로 만든 것이니까요.

근데 신기한건 PrincipalDetailsService로 만든 Key-Value는 일반적인 Session에 안들어갑니다.

그럼 어디에 들어가냐면, Session영역 안의 SecurityContextHolder에 들어가게 됩니다.

그 내부에 PrincipalDetails가 아니라, Authentication이라는 객체 안에 PrincipalDetails를 집어 넣어서 SecurityContextHolder안에 들어갑니다.

그러므로 User정보를 찾으려면 Session - SecurityContextHolder - Authentication - PrincipalDetails을 찾아야 하는 것입니다.

마지막인 PrincipalDetails 내부에 User 오브젝트가 있는 것입니다.

굉장히 귀찮죠????

스프링부트에서는 이렇게 찾지말라고 어노테이션을 하나 지원해주고 있습니다.

그 어노테이션 이름이 AuthenticationPrincipal입니다.

이 어노테이션이 있으면 Authentication에 바로 접근할 수 있어요

그래서 그 내부에 있는 PrincipalDetails를 접근하기 위해 다음과 같이 입력합니다.

만약 기존의 스프링방식대로 하려면 

여기로 들어가서 auth.getPrincipal()해야 세션을 찾을 수 있습니다.

어노테이션을 이용해서 하는게 훨씬 편하겠죠???

 

계속해서 회원정보 수정을 만들어보겠습니다.

회원정보 수정은 POST방식으로 이루어지기 때문에 Model에 담아서 전달해야 합니다.

파라미터에 Model도 같이 넣어주겠습니다.

그리고 이렇게 model에 principal에 getUser를 넘기면 값을 전달받은 model에는 princpal이 key-value형태로 담기게 되고 계속해서 재사용 할 수 있게 됩니다.

미리 구현된 update.jsp에서 공백이었던 username값을 ${}를 이용하여 이렇게 표현 가능합니다.

get메서드는 따로 필요하지 않고 principal에 담긴 username을 그대로 입력해야 합니다.

그래서 다음과 같이 모든 value값을 $와 {}를 이용해서 표현할 수 있습니다.

하나의 세션에 user의 모든 정보를 가져와서 계속해서 재사용할 수 있으니 굉장히 편리하죠?

근데 스프링부트에선 이것보다 더 쉬운 방법을 지원해줍니다.

pom.xml로 가보면

여기에 security-taglibs를 지원하고 있습니다.

이 라이브러리가 JSP쓸 때 쓰는건데, header.jsp로 가서 

이렇게 입력하면 인증된 정보에 접근하는 방법인데요.

세션에 접근하는 방법이라 생각하면 좋겠습니다.

그리고 property = "principal"이라고 적으면 세션 정보에 접근할 수 있습니다.

하나의 키워드라고 생각하시면 되겠습니다.

그래서 var도 principal이라고 작성하면 어디에 담을 것인지 설정할 수 있습니다.

그럼 이제 jsp의 모든 페이지에서 ${prinicpal}이렇게 적으면 principal에 접근이 가능합니다.

단, header.jsp를 모든 jsp를 가지고 있을 때 말이지요.

왜 property가 하필 principal일까요?

그건 저도 모르겠습니다. 스프링이 정한 규칙이라서 저도 몰라요

 

그럼 따로 모델에 안넘겨도 되겠죠?

UserController의 model.add~와 파라미터로 넘겨받은 model을 지웁니다.

우린 security - taglibs를 사용하고 있기 때문에 굳이 model에 담아서 안넘겨도 됩니다.

그리고 

이런식으로 prinicipal내부의 user속에 name이든, username이든, email이든 담겨 있으므로 user를 추가해줍니다.

그러므로 JSP할 때는 이 라이브러리를 꼭 쓰는 것을 추천드립니다.

리액트나 플러터를 할 때에는 이런걸 안쓸거에요

다 js로 작성하기 때문에요.

하지만 회사에서는 아직도 JSP를 쓰는 곳이 많기 때문에 잘 활용하면 굉장히 좋겠습니다.

감사합니다.

728x90
반응형
Comments