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를 반환하도록 다음과 같이 코드를 작성해준 뒤 다시 로그인 처리를 해보면 정상적으로 처리되는 것을 확인할 수 있다.
<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가 반환된것을 확인할 수 있다.