• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

로그인 성공 후 어떻게 진행되는지 이해가 안갑니다.

24.04.08 21:23 작성 조회수 332

0

@Override

protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,

Authentication auth) throws IOException, ServletException {

String userName = ((User) auth.getPrincipal()).getUsername();

UserDto userDetails = userService.getUserDetailsByEmail(userName);

byte[] secretKeyBytes = Base64.getEncoder().encode(environment.getProperty("token.secret").getBytes());

SecretKey secretKey = Keys.hmacShaKeyFor(secretKeyBytes);

Instant now = Instant.now();

String token = Jwts.builder()

.subject(userDetails.getUserId())

.expiration(Date.from(now.plusMillis(Long.parseLong(environment.getProperty("token.expiration_time")))))

.issuedAt(Date.from(now))

.signWith(secretKey)

.compact();

res.addHeader("token", token);

res.addHeader("userId", userDetails.getUserId());

}

 

여기서 로그인 성공 후 토큰이 발급된 뒤에

@Component

@Slf4j

public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<AuthorizationHeaderFilter.Config> {

Environment env;

public AuthorizationHeaderFilter(Environment env) {

super(Config.class);

this.env = env;

}

public static class Config {

// Put configuration properties here

}

@Override

public GatewayFilter apply(Config config) {

return (exchange, chain) -> {

ServerHttpRequest request = exchange.getRequest();

if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {

return onError(exchange, "No authorization header", HttpStatus.UNAUTHORIZED);

}

HttpHeaders headers = request.getHeaders();

Set<String> keys = headers.keySet();

log.info(">>>");

keys.stream().forEach(v -> {

log.info(v + "=" + request.getHeaders().get(v));

});

log.info("<<<");

String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);

String jwt = authorizationHeader.replace("Bearer", "");

// Create a cookie object

// ServerHttpResponse response = exchange.getResponse();

// ResponseCookie c1 = ResponseCookie.from("my_token", "test1234").maxAge(60 60 24).build();

// response.addCookie(c1);

if (!isJwtValid(jwt)) {

return onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED);

}

return chain.filter(exchange);

};

}

private Mono<Void> onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {

ServerHttpResponse response = exchange.getResponse();

response.setStatusCode(httpStatus);

log.error(err);

byte[] bytes = "The requested token is invalid.".getBytes(StandardCharsets.UTF_8);

DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);

return response.writeWith(Flux.just(buffer));

// return response.setComplete();

}

private boolean isJwtValid(String jwt) {

byte[] secretKeyBytes = Base64.getEncoder().encode(env.getProperty("token.secret").getBytes());

SecretKey signingKey = new SecretKeySpec(secretKeyBytes, SignatureAlgorithm.HS512.getJcaName());

boolean returnValue = true;

String subject = null;

try {

JwtParser jwtParser = Jwts.parserBuilder()

.setSigningKey(signingKey)

.build();

subject = jwtParser.parseClaimsJws(jwt).getBody().getSubject();

} catch (Exception ex) {

returnValue = false;

}

if (subject == null || subject.isEmpty()) {

returnValue = false;

}

return returnValue;

}
여기로 넘어 오는 게 맞나요?

그리고 그 뒤에 어떻게 진행되는지 설명 부탁드립니다!!

답변 2

·

답변을 작성해보세요.

0

안녕하세요, 이도원입니다.

말씀하신 내용처럼, apigateway-service에서 사용자의 로그인 요청을 받게 되면, user-service로 해당 요청을 보내게 됩니다. user-service에서는 로그인 성공일 경우 successfulAuthentication 메소드에서 Token 생성 된 유효기간 등의 정보를 Http Response Header에 저장해서 apigateway-service로 오게 됩니다. apigateway-servcei 에서 요청 (Http Request)가 전달 되었으니, 응답 (Http Response)도 apigateway-servcei로 가게 된다고 이해하시면 좋을 것 같습니다. 이 작업으로 Login 요청이 끝나게 되면 요청한 클라이언트에게는 Http Response Header에 user-service에 의해 발생 된 토큰이 저장된 것을 확인하실 수 있으며, 이 Token을 다음번 서비스 사용부터 (회원 목록 조회, 상품 조회 등의 비즈니스 메소드) 사용하게 됩니다.

apigateway-servcei의 apply 메소드에서는 제일 먼저 처리하는 작업이 사용자의 요청에 Token에 저장되어 있는지 그리고 해당 토큰이 유효한지를 검사하여 해당 요청을 user-service로 전달할지 order-service로 전달할 지 등을 결정하게 됩니다.

말씀하신 질문처럼 user-service의 successfulAuthentication 메소드와 apigateway-service의 apply 메소드는 하나의 동작에서 처리되는 것이 아니라, 각각 분리된 동작이라고 이해하셔야 합니다.

추가 질문 사항이 있으시면 다시 글 남겨 주세요.

감사합니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.04.08

안녕하세요, 인프런 AI 인턴입니다.

로그인이 성공한 후 JWT 토큰을 발급하고 그 이후의 프로세스에 대해 궁금하신 것 같습니다. 말씀하신 successfulAuthentication 메소드에서 사용자 인증에 성공했을 때 JWT 토큰을 생성하고, 헤더에 해당 토큰과 사용자 ID를 추가하여 클라이언트에 반환하는 과정을 설명하신 것으로 보입니다. 이후 AuthorizationHeaderFilter를 통해 들어온 요청에 대해 JWT 토큰의 유효성을 검사하는 과정을 설명하셨습니다.

강의 중 “Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)“에서도 비슷한 질문이 있었습니다. 사용자가 로그인하여 JWT 토큰을 발급받으면, 그 토큰을 이용하여 다른 서비스에 접근할 때 요청 헤더에 토큰을 포함시켜 보내는 방식입니다. 해당 토큰은 서버에서 유효성 검사를 거쳐 서비스 제공 여부를 결정하게 됩니다.

로그인 성공 후 토큰 발급이 완료되면 클라이언트는 이 토큰을 저장하고, 다음에 서버로 요청을 보낼 때 Authorization 헤더에 Bearer 키워드와 함께 이 토큰을 포함하여 전송해야 합니다. 이후 요청받은 서버 또는 API Gateway에서는 토큰의 유효성을 검증(예: 서명이 유효한지, 만료되지 않았는지 등)한 후 요청을 처리합니다.

위에서 언급한 AuthorizationHeaderFilter는 Spring Cloud Gateway에서 사용되며, 핵심 기능은 들어오는 요청의 Authorization 헤더를 검사하여 JWT 토큰의 유효성을 확인하는 것입니다. 유효하지 않은 경우에는 요청 처리를 중단하고 에러 응답을 반환합니다.

이 과정이 성공적으로 이루어진다면, 토큰이 유효함을 인증받은 사용자는 권한이 필요한 자원에 접근할 수 있게 됩니다. 이는 마이크로서비스 간의 보안된 통신을 가능하게 하며, 각 서비스마다 별도의 인증처리를 하지 않아도 되는 이점을 제공합니다.

관련하여 추가적인 설명이나 질문이 있으시면, 언제든지 질문해 주세요.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.