로그인 후 'userId'가 'localStorage'에 저장되지 않는 문제

gminnimk·2024년 11월 8일
0

문제 해결

목록 보기
6/18



로그인 후 'userId'가 'localStorage'에 저장되지 않는 문제




📜 문제 상황

  • 로그인 성공 후 'userId'가 'localStorage'에 올바르게 저장되지 않는 문제가 발생.

  • 'accessToken' 및 'refreshToken'이 올바르게 저장되었음을 확인.

  • 'userId'가 'localStorage'에서 'undefind'으로 표시.

  • /api/waste/records/users/{userId} 와 같은 API 호출에서 'userId'를 사용하려고 할 때 문제가 발생하여 사용자 식별이 누락되어 '403 Forbidden'과 같은 오류가 발생.




📜 문제 원인


📄 백엔드 응답 구조:

  • 백엔드 로그인 API는 'TokenResponseDto' 내에서 'userId'를 반환할 것으로 예상

  • 'TokenResponseDto'가 'userId'를 포함하도록 올바르게 설정되지 않았으며 서비스 로직에서 'userId'가 전달되지 않아 프론트가 이에 액세스할 수 없음을 확인.


- 로그인 API

    /**
     * 로그인 API
     *
     * @param requestDto 로그인 요청 데이터
     * @return 발급된 토큰 응답 데이터
     */
    @PostMapping("/login")
    public ResponseEntity<ApiResponse> login(@Valid @RequestBody LoginRequestDto requestDto) {
        TokenResponseDto responseDto = userService.login(requestDto);
        ApiResponse response = ApiResponse.builder()
            .msg(ResponseText.AUTH_LOGIN_SUCCESS.getMsg())
            .statuscode(String.valueOf(HttpStatus.OK.value()))
            .data(responseDto)
            .build();
        return ResponseEntity.status(HttpStatus.OK).body(response);
    }

  • 기존 TokenResponseDto
package com.sw.ecogrowbackend.domain.auth.dto;

import lombok.Getter;

@Getter
public class TokenResponseDto {
	// userId 필드 추가 필요
    private String accessToken;
    private String refreshToken;

    public TokenResponseDto(String accessToken, String refreshToken) {
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
    }
}

  • 기존 로그인 메서드
    /**
     * 로그인 로직
     *
     * @param requestDto 로그인 요청 데이터. 사용자 이름, 패스워드, 역할을 포함함.
     * @return TokenResponseDto 로그인 성공 시, 액세스 토큰과 리프레시 토큰을 반환함.
     * @throws CustomException 사용자 이름이 존재하지 않는 경우, 탈퇴한 사용자, 비밀번호 불일치, 역할 불일치
     */
    public TokenResponseDto login(LoginRequestDto requestDto) {
        User user = userRepository.findByUsername(requestDto.getUsername())
            .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

        if (!passwordEncoder.matches(requestDto.getPassword(), user.getPassword())) {
            throw new CustomException(ErrorCode.INCORRECT_PASSWORD);
        }

        String accessToken = jwtUtil.createAccessToken(user.getUsername(), user.getRole().toString());
        String refreshToken = jwtUtil.createRefreshToken(user.getUsername(), user.getRole().toString());

        refreshTokenService.saveRefreshToken(user.getId(), refreshToken);

        return new TokenResponseDto(accessToken, refreshToken); // 이 부분 개선 필요
    }




📜 문제 해결


  • 백엔드에서 'TokenResponseDto' 구조 확인

  • 백엔드에서 TokenResponseDto에 userId가 필드로 포함되어 있는지 확인하고 userId가 TokenResponseDto 생성자 내에 올바르게 할당되었는지 확인.



  • 개선된 TokenResponseDto userId가 필드로 추가
package com.sw.ecogrowbackend.domain.auth.dto;

import lombok.Getter;

@Getter
public class TokenResponseDto {
    private Long userId;
    private String accessToken;
    private String refreshToken;

    public TokenResponseDto(Long userId, String accessToken, String refreshToken) {
        this.userId = userId;
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
    }
}



  • 개선된 로그인 메서드
    /**
     * 로그인 로직
     *
     * @param requestDto 로그인 요청 데이터. 사용자 이름, 패스워드, 역할을 포함함.
     * @return TokenResponseDto 로그인 성공 시, 액세스 토큰과 리프레시 토큰을 반환함.
     * @throws CustomException 사용자 이름이 존재하지 않는 경우, 탈퇴한 사용자, 비밀번호 불일치, 역할 불일치
     */
    public TokenResponseDto login(LoginRequestDto requestDto) {
        User user = userRepository.findByUsername(requestDto.getUsername())
            .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

        if (!passwordEncoder.matches(requestDto.getPassword(), user.getPassword())) {
            throw new CustomException(ErrorCode.INCORRECT_PASSWORD);
        }

        String accessToken = jwtUtil.createAccessToken(user.getUsername(), user.getRole().toString());
        String refreshToken = jwtUtil.createRefreshToken(user.getUsername(), user.getRole().toString());

        refreshTokenService.saveRefreshToken(user.getId(), refreshToken);

        return new TokenResponseDto(user.getId(), accessToken, refreshToken); // 이 부분 개선 필요
    }



  • RefreshTokenService 로직에도 마찬가지로 TokenResponseDto 가 user의 Id를 반환할 수 있게 user.getId() 를 추가




  • LoginForm.js 코드에 localStorage 에 userId 추가
 const handleLogin = async (e) => {
    e.preventDefault();

    try {
      const response = await login(formData);

      console.log('로그인 응답:', response);

      const {accessToken, refreshToken, userId} = response.data.data; // Adjust based on actual response structure

      // 로컬 스토리지에 저장
      localStorage.setItem('token', accessToken);
      localStorage.setItem('refreshToken', refreshToken);
      localStorage.setItem('userId', userId);

      setMessage('로그인 성공!');
      setIsMessageVisible(true);
      setTimeout(() => {
        setIsMessageVisible(false);
        navigate('/');
      }, 1000);
    } catch (error) {
      console.error("Login error:", error);
      setMessage('로그인 실패. 다시 시도해 주세요.');
      setIsMessageVisible(true);
    }
  };

📢 값 확인

  • 정상적으로 userId의 값이 들어온 것을 확인.

  • 마이 페이지에서 인증된 사용자의 쓰레기 기록들을 전부 가져오는 API 호출 성공.

0개의 댓글