본문 바로가기
Study in Bootcamp/Main Project

[Main Project] Day 9 : 로그인 수정하기

by Bhinney 2022. 11. 19.

본 글은 프로젝트를 기록하기 위해 적은 글 입니다.

수정이 될 수 있으며, 정확하지 않을 수 있습니다.


📌 Login 시 Authority 적용

  • https://bhinney.tistory.com/138
  • 위의 블로그를 보면 hasRole()이 되지 않았던 문제가 있던 걸 알 수 있다.
  • 코드를 하나씩 뜯어가면서 다시 보았더니 권한은 주었으나 GrantedAuthority로 권한을 주지 않았던 것이다.
  • 그래서 Provider의 내용을 아래 코드처럼 수정해주었고, Claim으로 받았던 부분들을 모두 Map으로 수정해주었다.
  • 그랬더니 작동이 되었다...!!!!!!!
  • Config 파일도 아래처럼 코드를 수정해서 확인해보았더니 아래 사진처럼 잘 되었다.!
/* Security Config.java */

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
   http
      .headers().frameOptions().sameOrigin()
      .and()
      .csrf().disable()
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      .formLogin().disable()
      .httpBasic().disable()
      .apply(new JwtSecurityConfig(securityProvider))
      .and()
      .authorizeHttpRequests(authorize -> authorize
            .antMatchers(HttpMethod.POST, "/members/signup").permitAll()
            .antMatchers(HttpMethod.POST, "/login").permitAll()
            .antMatchers(HttpMethod.POST, "/login/oauth").permitAll()
            .antMatchers(HttpMethod.GET, "/members/client/**").hasRole("CLIENT")
            .antMatchers(HttpMethod.PATCH, "members/client/**").hasRole("CLIENT")
            .antMatchers(HttpMethod.GET,"/members/seller/**").hasRole("SELLER")
            .antMatchers(HttpMethod.PATCH, "/members/seller/**").hasRole("SELLER")
            .antMatchers(HttpMethod.DELETE, "/members/**").hasAnyRole("CLIENT", "SELLER")
            .anyRequest().permitAll()
      )
      .exceptionHandling()
      .authenticationEntryPoint(new MemberAuthenticationEntryPoint())
      .accessDeniedHandler(new MemberAccessDeniedHandler());

   return http.build();
}
/* JwtProvider.java */

public Authentication getAuthentication(String accessToken) {

   /* 1. 토큰 복호화 */
   Map<String, Object> claims = parseClaims(accessToken);

   /* 만약 복호화 한 토큰 안에 권한이 없으면 예외 던지기 */
   if (claims.get(AUTHORITIES_KEY) == null) {
      throw new BusinessLogicException(ExceptionCode.NOT_FOUND_AUTHORITIES);
   }

   /* 🐥 권한이 있다면, 권한 가져오기 */
   List<GrantedAuthority> authorities = authorityUtils.createAuthorities((String)claims.get(AUTHORITIES_KEY));

   /* UserDetails 객체를 만들어 Authentication 리턴 */
   UserDetails principal = new User((String)claims.get("username"), "", authorities);

   /* 2. 권한이 잘 리턴 되는지 확인 */
   log.info("2. 리턴 된 권한 : " + principal.getAuthorities());

   return new UsernamePasswordAuthenticationToken(principal, null, authorities);
}

  • 왼쪽은 유효하지 않은 토큰을 헤더로 보냈을때이고, 오른쪽은 유효한 토큰을 보냈을 때 나오는 모습이다.

📌 클래스 정리

  • 어제는 토큰 파트를 클래스 정리하였다면 오늘은 소셜 파트 클래스를 정리하였다.
  • Contoller, Sevice에 소셜 로그인 부분을 옮기고 정리하는데 다른 부분은 다 되고 리다이렉트 부분만 남았다.
  • 하나씩 옮기면서 잘 돌아가는 지 확인하다보니까 오래걸렸다.
  • 옮기다보니  코드 흐름을 전보다 이해가 되었다.
  • 그래서 안 부분은 주석으로 정리해서 커밋을 하였다.
  • 이것들은 다 메인 끝나고 깃헙에 하나 정리하는 레포지를 파서 올릴까한다!
/* 🟡 소셜 로그인 */
@Transactional
public TokenDto socialLogin(LoginRequestDto loginRequest) {

   /* 로그인 기반으로 "Authentication" 토큰 생성 */
   UsernamePasswordAuthenticationToken authenticationToken = loginRequest.toAuthentication();

   Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);

   /* 토큰 생성 -> 여기서 역할을 사용하기 때문에 이 전에 역할이 저장되어야 함 */
   TokenDto tokenDto = securityProvider.generatedTokenDto(authentication);

   RefreshToken userRefreshToken = refreshTokenRepository.findRefreshTokenByKey(loginRequest.getEmail());
   if (userRefreshToken == null) {

      /* 토큰이 저장되어 있지 않다면, 등록 */
      userRefreshToken = RefreshToken.builder()
         .key(loginRequest.getEmail())
         .value(tokenDto.getRefreshToken())
         .build();
      refreshTokenRepository.saveAndFlush(userRefreshToken);
   } else {

      /* 저장되어 있다면, 업데이트 */
      userRefreshToken.updateValue(tokenDto.getRefreshToken());
      refreshTokenRepository.saveAndFlush(userRefreshToken);
   }

   return tokenDto;
}

🔥 해내고 싶은 일과 해야 하는 일

  • 프론트 분께서 Get으로 헤더에 Authorization 요청을 날리면 로그인처럼 보일 수 있는 걸 달라고 하셔서 그 부분을 해봐야 한다.
  • 소셜 redirect Url을 좀더 간결하게 수정하고 싶어서 고민 중이다. 해당 부분이 해결되고 잘 돌아가면 좋을 것 같다.
  • 리프레시로 엑세스 토큰을 재발급 받는 로직을 구현하였는데, 이제 이걸 어떻게 요청을 받을지를 고민해서 구현해봐야 할 것 같다.
  • Redis에 대한 공부를 좀 더 해보려고 한다. 해당이 되면 로그아웃도 조금 더 간결하게, 리프레시도 다르게 구현할 수 있지 않을까.

댓글