Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bbaemin spring security, jwt #33

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

CHANEE-personal
Copy link
Collaborator

@CHANEE-personal CHANEE-personal commented Mar 1, 2023

  1. spring securitry 적용
  2. jwt와 spring security를 활용한 로그인 기능 구현
  3. 로그인 test case 구현 예정

@CHANEE-personal CHANEE-personal self-assigned this Mar 1, 2023
Comment on lines +32 to +33
public JwtTokenProvider(@Value("${spring.jwt.secret}") String secret,
@Value("${spring.jwt.token-validity-in-seconds}") long tokenValidityInMilliseconds,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@value 대신에 ConfigurationProperties를 쓰는게 더 좋을 것 같습니다. 왜 좋은지 생각해 보시겠어요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 넵 한 번 알아보겠습니다!

@@ -16,6 +18,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 필요한 것인가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삭제 완료했습니다!

import org.bbaemin.user.repository.UserRepository;
import org.bbaemin.user.vo.User;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.security.authentication.*;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Change it to actual import statements

@Transactional(readOnly = true)
@Service
@RequiredArgsConstructor
public class UserService {

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@f-lab-lyan UserService가 위와 같은 시큐리티 관련 클래스에 의존성을 가지는 부분에 대해 어떻게 생각하시는지 궁금합니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제 생각은 당연히 의존하지 않는 것이 좋을 것 같습니다. AuthenricationService등을 만들어서 처리해야하지 않을까싶은 생각이 듭니다.

}

private Authentication authenticate(String userEmail, String password) {
try {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위 로그인 처리나 인증 관련 메소드는 이왕이면 Spring Security의 handler나 filter들을 구현해서 처리하는 게 더 좋지 않을까요?


@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class User {
public class User implements UserDetails {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@f-lab-lyan User 엔티티를 UserDetails의 구현체로 사용하는 것에 대해 어떻게 생각하시나요?

Copy link
Collaborator

@f-lab-lyan f-lab-lyan Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 저도 궁금한 부분인데요. 왜 UserDetails란 구현체가 User와 묶여야 하는지 정확히 모르겠어요. 아, 설명이 너무 대충인 것 같아서 잠깐 추가하면, Security에서 필요한 부분을 서비스에 녹여내면, 구현할 때는 편하겠지만, 실제로 확장하거나 수정할 때, 상관없는 시큐리티 이슈를 확인해야할 수도 있어요. 그렇게 하는 게 좋은 것인지 모르겠다는 말이었습니다.

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebSecurityConfigurerAdapter를 상속해서 설정하는 방법은 현재 deprecated된 것으로 아는데요! 현재 권장되는 방법으로 설정해보는 게 좋을 것 같습니다.

@@ -71,4 +72,9 @@ public ApiResult<Void> quit(@PathVariable Long userId) {
userService.quit(userId);
return ApiResult.ok();
}

@PostMapping("/login")
public JwtResponse login(@Validated @RequestBody LoginRequest loginRequest) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 ApiResult로 return해주지 않는 건가요?


@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
log.info("UsernameFilter");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클래스명은 AuthorizationFilter인데 권한을 체크하고 있는 것 같지는 않아요!

} else {
Authentication authentication = jwtTokenProvider.getAuthentication(accessToken);
User getUser = userRepository.findByEmail(authentication.getName())
.orElseThrow(() -> new NoSuchElementException("email : " + authentication.getName()));
Copy link
Collaborator

@yeonkyungJoo yeonkyungJoo Mar 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JwtAuthenticationFilter, JwtAuthorizationFilter에 대한 의문인데요!
Spring Security 프로세스가
UsernamePasswordAuthenticationToken 같은 인증 전 토큰을 AuthenticationManager에 넘기면,
각 Provider들이 UserDetailsService에서 loadByUsername을 통해 조회하고
조회 성공 시 권한이 담긴 토큰으로 리턴해주는 방식이잖아요.

  1. Authentication authentication = jwtTokenProvider.getAuthentication(accessToken);
    여기서 이걸 왜 실행하는 건가요? 그리고 JwtTokenProvider에서 getAuthentication(accessToken)을 하면 권한이 담긴 UsernamePasswordAuthenticationToken을 넘겨주는 게 맞는 건가요? 아직 인증 전인데요!
  2. 여기서 user를 조회하는 게 맞는 건가요? 지금 JwtAuthorizationFilter에서 authenticate()하면 조회를 할 텐데요. 바로 위에 있는 getAuthentication(accessToken)에서도 user를 조회하시더라구요!

시큐리티 설정이 메인은 아니지만,
프로세스의 각 필터들을 알맞게 쓰고 계신 건가에 대한 의문이 들었어요!
물론 제가 잘못 알고 있는 걸 수도, 찬희님 코드를 놓친 걸 수도 있습니다 :-)

.formLogin().disable()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@f-lab-lyan frontend, backend 나눠질 때 STATELESS로 안 할 수도 있나요? 그냥 세션을 사용하는 거요!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이부분은 제가 아니라 찬희님이 대답해 주셔야할 것 같은 느낌이 드네요. :-)

Copy link
Collaborator

@yeonkyungJoo yeonkyungJoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적인 느낌은
인증을 어느 클래스에서 하는 건지 파악이 어렵다는 거였습니다.
JwtAuthenticationFilter인지, JwtAuthorizationFilter인지
아니면 UserService의 login(), authenticate() 메소드인지요!
같이 정리해보는 게 좋을 것 같아요!

@CHANEE-personal
Copy link
Collaborator Author

전체적인 느낌은 인증을 어느 클래스에서 하는 건지 파악이 어렵다는 거였습니다. JwtAuthenticationFilter인지, JwtAuthorizationFilter인지 아니면 UserService의 login(), authenticate() 메소드인지요! 같이 정리해보는 게 좋을 것 같아요!

아무래도 저도 처음 적용을 시켜보다보니 놓친 부분이 많은거 같습니다. 좀 더 알아보도록 하겠습니다!

@CHANEE-personal CHANEE-personal marked this pull request as draft March 6, 2023 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants