본문 바로가기
Java Spring/Security

SessionId 사용하여 로그인한 회원이 작성한 글 DB에 저장하기

by GGShin 2022. 8. 15.

Member(회원)와 Post(게시글) entity가 1 : N 관계일 때,

로그인 한 회원이 글을 작성했을 때 DB에 회원 정보와 함께 저장되도록 하는 기능을 구현해보았습니다.

 

방법을 몰라서 이런 저런 시도를 두 시간 가량 해보다가 구글링과 그 간 배웠던 지식들을 토대로 결국에는 구현해낼 수 있었습니다.

필요하신 분께 도움이 되면 좋겠고, 더 좋은 방법이 있다면 알려주시면 감사하겠습니다.

 

여기서는 Form login을 사용했고 session id로 인증하는 방법을 사용했습니다.

 

1. SecurityFilterChain을 보면

"/v1/post/**" 경로에는 인증된 사용자만이 접근하여 글을 작성할 수 있도록 권한 설정을 해두었습니다.

@Configuration
public class AppSecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    };

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.headers().frameOptions().disable();
    
        http.authorizeRequests()
                .antMatchers("/v1/post/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .formLogin()
                .loginPage("/login");

        return http.build();
    }
}

 

여기까지는 어렵지 않게 구현했는데, /v1/post 경로로 진입하여 게시글을 저장하려고 할 때 Post table에 게시글 정보를 저장하는 방법을 알아내는데 노력이 필요했습니다. 

 

<무엇을 알아야 했었는가?>

1. 로그인 한 회원의 정보를 어떻게 가져올 수 있을 지 알아야 했습니다.

2. 로그인 한 회원의 정보를 알 수 있게 되었다면 게시글(Post) DB에 회원 정보와 같이 저장할 수 있어야 했습니다.

 

로그인은 성공했지만, 현재 로그인한 유저의 정보를 어떻게 알 수 있는지 그 방법을 찾아야 했습니다.

UserDetails에 현재 로그인된 유저의 정보를 알 수 있다는 것을 떠올렸고 이를 활용하는 방법으로 시도해봤습니다.

UserDetails에 대한 설명

 

postPost(메서드명이 좀 헷갈리게 지어진 것 같습니다 ㅎㅎ;) method의 파라미터로 @AuthenticationPrincipal을 추가해서 현재 로그인된 유저의 정보를 받아오게 해보았습니다.

 

@PostMapping
    public ResponseEntity postPost(@AuthenticationPrincipal PrincipalDetails principalDetails,
                                   @Valid PostDto.Post postDto) {

        //postDto to Post so that Service can do its job
        Post post = postMapper.postDtoToPost(postDto);

        long memberId = principalDetails.getUserId();
   
        Member foundMember = memberService.findVerifiedMember(memberId);

        post.setMember(foundMember);

        //service
        Post createdPost = postService.createPost(post);

        //post entity to response dto
        PostDto.Response response = postMapper.postToPostResponse(createdPost);

        log.info(post.getMember().getName() + " post Success");

        return new ResponseEntity<>(response, HttpStatus.CREATED);

    }

 

@AuthenticationPrincipal에 대한 공식적인 설명은 아래 사진에 나온 것 처럼

"Authentication.getPrincipal()을 메서드의 파라미터로 사용할 수 있도록 해주는 annotation" 입니다.

Principal이 인증된 유저의 정보니까 이 annotation을 사용하면 되는 게 맞는 것 같습니다.

 

🏷 해당 애노테이션에 대해 찾아보며 참고한 블로그(엔꾸꾸님)에서는 
"@AuthenticationPrincipal 애노테이션을 사용하면 UserDetailsService에서 Return한 객체를 파라메터로 직접 받아 사용할 수 있다." 라고 설명해주셨습니다.

 

@AuthenticationPrincipal에 대한 설명

이 방법으로 "1. 로그인 한 회원의 정보를 어떻게 가져올 수 있는가" 부분을 해결했습니다.

 

postPost 메서드 파라미터에서 사용한 PrincipalDetails은 UserDetails를 구현하고 있는 제가 만든 구현체입니다. 그리고 PrincipalDetails class 내부에 기본적으로 override 해야하는 메서드 외에 getUserId() method를 추가하여 유저의 id를 가져올 수 있도록 하였습니다. 유저 id를 이용해서 저장된 유저 entity를 찾고, 게시글 등록 시에 필요한 유저 정보를 제공할 수 있었습니다. 

이렇게 해서 알아내야 하는 항목 두번째 "2. 게시글(Post) DB에 회원 정보와 같이 저장하기"도 해결할 수 있었습니다.

 

한 번 테스트한 결과를 보여드리면,

 

 

이렇게 MEMBER_ID와 잘 연결되어 DB에 저장된 것을 확인할 수 있었습니다.

 

방법을 알기전에는 좀 막막했었는데, 해당 내용을 공부하면서 security에서 user 정보를 어떻게 다루는 지 조금 더 알게되어 뿌듯합니다. ㅎㅎ

 

다음번에는 JWT를 사용하는 방식으로 구현해보려고 합니다!

 

 


참고자료

 

https://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#jc-form

 

Spring Security Reference

The authenticator is also responsible for retrieving any required user attributes. This is because the permissions on the attributes may depend on the type of authentication being used. For example, if binding as the user, it may be necessary to read them

docs.spring.io

https://docs.spring.io/spring-security/reference/servlet/authentication/rememberme.html

 

Remember-Me Authentication :: Spring Security

Remember-me or persistent-login authentication refers to web sites being able to remember the identity of a principal between sessions. This is typically accomplished by sending a cookie to the browser, with the cookie being detected during future sessions

docs.spring.io

 

[핵심적인 도움이 되었던 자료👏]

https://www.codejava.net/frameworks/spring-boot/get-logged-in-user-details

 

How to Get Logged-in User's Details with Spring Security

 

www.codejava.net

 

https://ncucu.me/137

 

Spring Security - @AuthenticationPrincipal

Spring Security - @AuthenticationPrincipal @AuthenticationPrincipal 로그인한 사용자의 정보를 파라메터로 받고 싶을때 기존에는 다음과 같이 Principal 객체로 받아서 사용한다. 하지만 이 객체는 SecurityCo..

ncucu.me

 

반응형