인증과 권한 [3] jwt 추가

최준호·2022년 3월 6일
0

Microservice Architecture

목록 보기
17/32
post-thumbnail

🔨UserDto 반환 받기

jwt를 추가하기 전에 UserDto값을 반환 받아서 토큰 값으로 만들 userId값을 가져와야한다.

@Slf4j
@RequiredArgsConstructor
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final UserService userService;
    private final Environment env;

    ...

    //로그인 성공했을 때 로직
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        String userEmail = ((User)authResult.getPrincipal()).getUsername();
        UserDto userDto = userService.getUserDetailsByEmail(userEmail);
    }
}

기존의 log만 찍었던 로직을 다음과 같이 입력 받은 email 값으로 userId값을 받아올 수 있도록 변경한다.

하지만 여기서 getUserDetailsByEmail()는 정의되지 않았기 때문에 에러가 날것이다. 또한 생성자에 UserService와 Enviroment값을 매개변수로 설정했기 때문에 WebSecurity에서 생성자로 Filter를 생성하는 부분에도 값을 넣어줘야한다.

@Configuration  //다른 bean들 보다 우선순위를 앞으로
@EnableWebSecurity  //security 어노테이션
@RequiredArgsConstructor
public class WebSecurity extends WebSecurityConfigurerAdapter {

    private final UserService userService;
    private final BCryptPasswordEncoder passwordEncoder;
    private final Environment env;
    ...

    private AuthenticationFilter getAuthenticationFilter() throws Exception {
        AuthenticationFilter authenticationFilter = new AuthenticationFilter(userService, env);
        authenticationFilter.setAuthenticationManager(authenticationManager()); //spring security에서 제공하는 manager 객체

        return authenticationFilter;
    }

    
}

먼저 WebSecurity 파일의 매개변수에 userSerivce와 env를 넣어준다.

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService{
    ...
    
    @Override
    public UserDto getUserDetailsByEmail(String userEmail) {
        UserEntity userEntity = userRepository.findByEmail(userEmail);
        //if(userEntity == null) throw new UsernameNotFoundException("user email 값이 유효하지 않습니다.");
        return new ModelMapper().map(userEntity, UserDto.class);
    }
}

그리고 UserDto를 반환하도록 다음과 같이 코드를 작성해준 뒤 다시 로그인 처리를 해보면 정상적으로 처리되는 것을 확인할 수 있다.

Jwt 추가

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

xml에 jwt를 추가해주고

...

token:
  expiration_time: 86400000 #ms단위
  secret: user_token

yml에 우리가 사용할 token 설정 값을 미리 지정해준다.

@Slf4j
@RequiredArgsConstructor
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final UserService userService;
    private final Environment env;
	
    ...

    //로그인 성공했을 때 로직
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        String userEmail = ((User)authResult.getPrincipal()).getUsername();
        UserDto userDto = userService.getUserDetailsByEmail(userEmail);

        String token = Jwts.builder()
                .setSubject(userDto.getUserId())    //token 내용
                .setExpiration(new Date(System.currentTimeMillis() + Long.parseLong(env.getProperty("token.expiration_time")))) //파기 날짜
                .signWith(SignatureAlgorithm.HS512, env.getProperty("token.secret"))    //token 생성 알고리즘과 키 값
                .compact();

        response.setHeader("token", token);
        response.setHeader("userId", userDto.getUserId());  //원래는 반환하지 않는 데이터이지만 확인용
    }
}

추가하여 로그인을 성공했을 때 다음과 같이 헤더에 token정보를 추가해서 반환하고

반환되는 값의 header 정보에도 token과 userid가 반환된것을 확인할 수 있다.

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글