티스토리 뷰

카테고리 없음

내 서비스 만드는 삽질기2

시간이nullnull한 가장 2023. 3. 23. 20:44

front는 react로, 소셜 로그인을 이용한 자체 서비스를 만들어보기로 했다.

 

react를 빨리 습득하기 위해 ebook의 힘을 빌렸다.

 

소셜 로그인을 구현하는 겸 시큐리티 공부도 쌓기 위해 인터넷 강의도 함께 했다.(https://inf.run/NWbk)

 

보통의 react + spring의 flow는 아래의 이미지와 같았다.

(https://velog.io/@heelieben/Google-Oauth2-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8React-Spring)

 

하지만 리액트쪽 코드 구현을 최소한으로 하기 위해 나의 소셜 로그인 플로우의 큰 틀은 다음과 같다.

 

1. backend에서 oauth2 기반 로그인 구현

2. front에서 backend의 oauth2 로그인 호출

3. 로그인 성공 시 front로 redirect

 

이미지로 도식화하면 아래와 같다.

 

 

그리하여 지금까지 만든것 

1. Front (react) - google 로그인, todo crud

2. Back (java) - 소셜 로그인 연동, jwt 토큰 생성/검증, todo API

3. Devops - ecr, ecs, codepipe라인을 통한 backend ci/cd

 

시연 동영상

 

그리하여 만들어진것

 

 

할 것

1. frontend 동작 시 바로 반응하도록 코드 수정

2. refresh 토큰의 위치는 어디에? refresh 어떻게 할 것인지

3. aws에 react ci/cd 작업

4. dev/prod 환경설정 분리

5. 소셜 로그인을 localhost가 아닌 실제 api에서 동작하도록 수정

6. form login 추가

7. 소셜 로그인 추가 (네이버)

 

어려웠던 것

0. 리액트 익히기

1. cors 설정 (추후 포스팅)

2. 수정api의 method는 patch? put?

3. websecurityconfigureradapter deprecated (https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter 를 참고하여 해결)

4. RESTFUL API SPEC (추후 포스팅)

 

해결하지 못한 문제

1. aop에서 설정한 Authentication은 controller에서 @AuthenticationPrincipal로 받아지지 않는 이유?

@Around(value = "@annotation(com.nullnull.mybodyrecord.aop.Api)")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            String bearerToken = parseBearerToken(request);
            Jws<Claims> jwt = Jwts.parserBuilder().setSigningKey(getSigninKey(SECRET_KEY))
                    .require("type", JwtTokenTypeEnum.ACCESS.getValue())
                    .build().parseClaimsJws(bearerToken);

            Long idx = Long.parseLong(jwt.getBody().getSubject());
//            SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
//            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(idx, null, AuthorityUtils.NO_AUTHORITIES);
//            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//            emptyContext.setAuthentication(authentication);
//            SecurityContextHolder.setContext(emptyContext);
            request.setAttribute("userIdx", idx);
            return joinPoint.proceed();
        } catch (ExpiredJwtException e){
            throw new UnauthorizedException("로그인이 만료되었습니다.");
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }

위 aop에서 setAttribute한 userIdx는 Controller에서 가져와지지만 주석처리한 코드처럼 SecurityContextHolder에 set한 authentication 객체는 @AuthenticationPrincipal annotation으로 불러와지지 않았다.. 무엇이 문제인지 아직 탐색중