인프런 커뮤니티 질문&답변

김준엽님의 프로필 이미지
김준엽

작성한 질문수

스프링 시큐리티 OAuth2

spring boot 3.1 security entryPoint 관련 질문입니다

작성

·

1.4K

·

수정됨

0

 

스프링부트 2.7.7 버전에서는 사용할때 아무 문제없던 코드들인데 3.1 버전 업데이트하면서 securityFilterChain 이부분 문법만 살짝 바뀐정도입니다
그런데

jwt 토큰에서 chain.doFilter(request, response); 까지 잘 넘어가고

비즈니스 로직인 service 단에서 에러가 터졌을때 (NullPointException,IllegalArgumentException)

에러가 났을경우

다시 엔트리포인트로 넘어와서 에러처리가 되는데 왜 이럴까요 ??

 

무슨 에러가 나든

엔트리포인트로 넘어오는데 엔트리포인트는 인증 실패일경우에 실행되어야하는걸로 알고있습니다

토큰값은 모두 유효하고 jwt 토큰 인증은 되었음에도 불구하고 엔트리포인트로 넘어가는 이유를 모르겠습니다

아래 에러는 비즈니스로직에서 에러 난 코드이며

 

 

2023-10-30T23:56:16.287+09:00 ERROR 26006 --- [nio-8081-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessApiUsageException: No enum constant com.tripcoach.core.domain.alarm.enums.AlarmType.COACH] with root cause

java.lang.IllegalArgumentException: No enum constant com.tripcoach.core.domain.alarm.enums.AlarmType.COACH

at java.base/java.lang.Enum.valueOf(Enum.java:273) ~[na:na]

at org.hibernate.type.descriptor.java.EnumJavaType.fromName(EnumJavaType.java:231) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]

at org.hibernate.type.descriptor.converter.internal.NamedEnumValueConverter.toDomainValue(NamedEnumValueConverter.java:53) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]

 

바로 에러코드 다음이

 

2023-10-30T23:56:16.291+09:00 ERROR 26006 --- [nio-8081-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] threw exception

java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "exception" is null

at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.resolveMethodByThrowable(ExceptionHandlerMethodResolver.java:146) ~[spring-web-6.0.12.jar:6.0.12]

at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.resolveMethod(ExceptionHandlerMethodResolver.java:134) ~[spring-web-6.0.12.jar:6.0.12]

 

 

엔트리포인트에서 넘어와버리네요

부족한 코드이지만 아무리 찾아도 모르겠어서 글 남깁니다.

 

아래 전체코드 첨부합니다

 

답변 2

0

김준엽님의 프로필 이미지
김준엽
질문자

import com.tripcoach.app_api.api.member.repository.MemberRepository;
import com.tripcoach.app_api.security.token.CustomAuthenticationToken;
import com.tripcoach.core.domain.member.entity.Member;
import com.tripcoach.core.domain.member.enums.OsType;
import com.tripcoach.core.domain.member.enums.SnsType;
import com.tripcoach.core.common.exception.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.transaction.annotation.Transactional;

import static com.tripcoach.core.common.apiresult.comcode.ComCode.LOGIN_FAIL;
public class CustomAuthenticationManager implements AuthenticationManager {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private MemberRepository memberRepository;


    @Override
    @Transactional
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        CustomAuthenticationToken customAuthenticationToken = (CustomAuthenticationToken) authentication;

        System.out.println("customAuthenticationToken.getSnsType() = " + customAuthenticationToken.getSnsType());

        String snsId = customAuthenticationToken.getSnsId();
        SnsType snsType = SnsType.valueOf(customAuthenticationToken.getSnsType());
        String fcmToken = customAuthenticationToken.getFcmToken();
        OsType osType = OsType.valueOf(customAuthenticationToken.getOsType());

        Member member = memberRepository.findBySnsIdAndSnsType(snsId, snsType)
                .orElseThrow(() -> new BadCredentialsException(LOGIN_FAIL));

        member.updateFcmToken(fcmToken);
        member.updateOsType(osType);

        UserDetails userDetails = userDetailsService.loadUserByUsername(String.valueOf(member.getIdx()));
        if (userDetails == null) {
            throw new BusinessException("로그인에 실패 했습니다.");
        }

        return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    }
}

import com.tripcoach.core.common.exception.exception.BusinessException;
import com.tripcoach.core.domain.member.entity.Member;
import io.jsonwebtoken.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

import static com.tripcoach.app_api.security.config.SecurityCode.*;
import static java.util.stream.Collectors.toList;

@Slf4j
@Component
public class JwtTokenProvider implements Serializable {
    private static final String SECRET_KEY = "";
    private static final long EXPIRATION_TIME = 1000 * 1800; // 30분초
//    private static final long EXPIRATION_TIME = 30 * 24 * 60 * 60 * 1000L; // 1달
    //    private static final long EXPIRATION_TIME = 300 * 600 * 100L; //300분


    /**
     * Jwt 생성
     */
    public String generateToken(Member member) {
        ArrayList<GrantedAuthority> roles = new ArrayList<>();
        roles.add(new SimpleGrantedAuthority(member.getGrade().label()));

        Date now = new Date();
        Date expiration = new Date(now.getTime() + EXPIRATION_TIME);
        return Jwts.builder()
                .setSubject(member.getIdx().toString())
                .claim("authorities", roles.stream().map(GrantedAuthority::getAuthority).collect(toList()))
                .claim("nickname", member.getNickname())  // 이 부분을 추가하여 nickname 클레임을 설정합니다
                .setIssuedAt(now)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }


    //    /**
//     * JWT 회원 정보 추출.
//     */
    public Claims getUsernameFromToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            throw new ExpiredJwtException(null, null, "토큰이 만료 되었습니다");
        } catch (MalformedJwtException e) {
            throw new BusinessException("잘못된 토큰입니다."); // 토큰이 잘못된 경우 처리할 내용
        }
    }

    public Claims getUsernameFromToken(String token, HttpServletRequest request) {
        Claims claims = null;
        try {
            claims = Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

        } catch (ExpiredJwtException e) {
            request.setAttribute(JWT_EXCEPTION.label(), EXPIRED_JWT_EXCEPTION);
        } catch (MalformedJwtException e) {
            request.setAttribute(JWT_EXCEPTION.label(), MALFORMED_JWT_EXCEPTION);
        } catch (UnsupportedJwtException e) {
            request.setAttribute(JWT_EXCEPTION.label(), UNSUPPORTED_JWT_EXCEPTION);
        } catch (SignatureException e) {
            request.setAttribute(JWT_EXCEPTION.label(), SIGNATURE_EXCEPTION);
        } catch (IllegalArgumentException e) {
            request.setAttribute(JWT_EXCEPTION.label(), ILLEGAL_ARGUMENT_EXCEPTION);
        }catch (NullPointerException e) {
            request.setAttribute(JWT_EXCEPTION.label(), NULL_POINT_EXCEPTION);
        }
        return claims;
    }


}

import com.tripcoach.app_api.api.member.repository.MemberRepository;
import com.tripcoach.core.domain.member.entity.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

@RequiredArgsConstructor
@Service("userDetailService")
public class CustomUserDetailsServiceImpl implements UserDetailsService {

    private final MemberRepository memberRepository;


    @Override
    public UserDetails loadUserByUsername(String idx) throws UsernameNotFoundException {
        Member member = memberRepository.findById(Long.valueOf(idx))
                .orElseThrow(() -> new UsernameNotFoundException("User not found with idx: " + idx));

        ArrayList<GrantedAuthority> roles = new ArrayList<>();
        roles.add(new SimpleGrantedAuthority(member.getGrade().label()));

        return new MemberContext(member, roles);
    }

}
import com.tripcoach.core.domain.member.entity.Member;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collection;

public class MemberContext extends User {

    private final Member member;

    public MemberContext(Member member, Collection<? extends GrantedAuthority> authorities) {
        super(String.valueOf(member.getIdx()), "beeb.tripcoach", authorities);
        this.member = member;
    }

    public Member getMember() {
        return member;
    }

    public Long getId() {
        return member.getIdx();
    }
}
import lombok.Getter;
import org.springframework.security.authentication.AbstractAuthenticationToken;

@Getter
public class CustomAuthenticationToken extends AbstractAuthenticationToken {
    private final String snsId;
    private final String snsType;
    private final String fcmToken;
    private final String osType;

    public CustomAuthenticationToken(String snsId, String snsType, String fcmToken, String osType) {
        super(null);
        this.snsId = snsId;
        this.snsType = snsType;
        this.fcmToken = fcmToken;
        this.osType = osType;
    }


    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return snsId;
    }


}

0

김준엽님의 프로필 이미지
김준엽
질문자

삭제된 글입니다

정수원님의 프로필 이미지
정수원
지식공유자

전체 실행 코드 공유 부탁드립니다

김준엽님의 프로필 이미지
김준엽
질문자

import com.tripcoach.app_api.security.exception.JwtAuthenticationEntryPoint;
import com.tripcoach.app_api.security.filter.CustomAuthenticationFilter;
import com.tripcoach.app_api.security.filter.JwtAuthenticationFilter;
import com.tripcoach.app_api.security.handler.CustomAccessDeniedHandler;
import com.tripcoach.app_api.security.handler.CustomAuthenticationFailureHandler;
import com.tripcoach.app_api.security.handler.CustomAuthenticationSuccessHandler;
import com.tripcoach.app_api.security.provider.CustomAuthenticationManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;

import static com.tripcoach.core.common.apiresult.comcode.ComCode.PERMIT_ALL;
import static org.springframework.security.config.Customizer.withDefaults;

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final CustomAccessDeniedHandler customAccessDeniedHandler;
    private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(withDefaults())
                .authorizeHttpRequests(authorizeRequests ->
                        authorizeRequests
                                .requestMatchers(PERMIT_ALL).permitAll()
                                .anyRequest().authenticated()
                )
                .exceptionHandling(exceptionHandling ->
                        exceptionHandling
                                .accessDeniedHandler(customAccessDeniedHandler)
                                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                )
                .sessionManagement(sessionManagement ->
                        sessionManagement
                                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                );

        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    // 커스텀 인증 필터
    @Bean
    public CustomAuthenticationFilter customAuthenticationProcessingFilter() {
        CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
        filter.setAuthenticationManager(customAuthenticationManager());
        filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler());
        return filter;
    }

    // 커스텀 인증 매니저
    @Bean
    public CustomAuthenticationManager customAuthenticationManager() {
        return new CustomAuthenticationManager();
    }
}

import com.fasterxml.jackson.annotation.JsonCreator;
import com.tripcoach.core.common.enumType.Constant;
import lombok.Data;
import lombok.Getter;

import java.util.Arrays;


public enum SecurityCode implements Constant {
    JWT_EXCEPTION("JWT_EXCEPTION", "JWT TOKEN 만료 되었거나 잘못 되었습니다."),
    EXPIRED_JWT_EXCEPTION("ExpiredJwtException", "토큰이 만료 되었습니다.\n토큰을 재발급 해주세요"),
    MALFORMED_JWT_EXCEPTION("MalformedJwtException", "손상된 토큰입니다.\n관리자에게 문의해주세요"),
    UNSUPPORTED_JWT_EXCEPTION("UnsupportedJwtException", "지원하지 않은 토큰 입니다."),
    SIGNATURE_EXCEPTION("SignatureException", "시그니처 검증에 실패한 토큰 입니다."),
    ILLEGAL_ARGUMENT_EXCEPTION("IllegalArgumentException", "관리자에게 문의해주세요"),
    NULL_POINT_EXCEPTION("NullPointException", "빈값 입니다");

    private final String label;
    private final String message;

    SecurityCode(String label, String message) {
        this.label = label;
        this.message = message;
    }

    public String label() {
        return label;
    }

    public String message() {
        return message;
    }

}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tripcoach.app_api.security.config.SecurityCode;
import com.tripcoach.core.common.apiresult.dto.ApiResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.PrintWriter;

import static com.tripcoach.app_api.security.config.SecurityCode.*;
import static com.tripcoach.core.common.apiresult.util.ApiUtils.error;
import static jakarta.servlet.http.HttpServletResponse.*;
import static org.apache.commons.codec.CharEncoding.UTF_8;


@Slf4j
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        SecurityCode jwtException = (SecurityCode) request.getAttribute(JWT_EXCEPTION.label());

//        String errorMessage = getErrorMessage(jwtException);

        String errorMessage = "관리자에게 문의해주세요";
        int errorCode = 400;

        if (jwtException != null) {
            switch (jwtException) {
                case EXPIRED_JWT_EXCEPTION:
                    errorMessage = EXPIRED_JWT_EXCEPTION.message();
                    errorCode = 401;
                    break;
                case MALFORMED_JWT_EXCEPTION:
                    errorMessage = MALFORMED_JWT_EXCEPTION.message();
                    errorCode = 401;
                    break;
                case UNSUPPORTED_JWT_EXCEPTION:
                    errorMessage = UNSUPPORTED_JWT_EXCEPTION.message();
                    errorCode = 401;
                    break;
                case SIGNATURE_EXCEPTION:
                    errorMessage = SIGNATURE_EXCEPTION.message();
                    errorCode = 401;
                    break;
                case ILLEGAL_ARGUMENT_EXCEPTION:
                    errorMessage = ILLEGAL_ARGUMENT_EXCEPTION.message();
                    errorCode = 400;
                    break;
                case NULL_POINT_EXCEPTION:
                    errorMessage = NULL_POINT_EXCEPTION.message();
                    errorCode = 400;
                    break;
                default:
                    errorMessage = JWT_EXCEPTION.message(); // 기본적으로 설정할 메시지
                    errorCode = 500;
                    break;
            }
        }


        response.setContentType("application/json");
        response.setCharacterEncoding(UTF_8);
        response.setStatus(errorCode);
        ApiResult<?> error = error(request.getServletPath(), errorMessage, errorCode);
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResponse = objectMapper.writeValueAsString(error);
        PrintWriter out = response.getWriter();
        out.print(jsonResponse);
        out.flush();
    }
}
import com.tripcoach.app_api.security.token.CustomAuthenticationToken;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter {


    public CustomAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {


        String snsId = request.getParameter("snsId");
        String snsType = request.getParameter("snsType");
        String fcmToken = request.getParameter("fcmToken");
        String osType = request.getParameter("osType");

        CustomAuthenticationToken customToken = new CustomAuthenticationToken(snsId, snsType, fcmToken, osType);

        return getAuthenticationManager().authenticate(customToken);
    }

}

 

김준엽님의 프로필 이미지
김준엽
질문자


import com.tripcoach.app_api.security.provider.JwtTokenProvider;
import com.tripcoach.app_api.security.service.CustomUserDetailsServiceImpl;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Slf4j
@RequiredArgsConstructor
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";
    private final CustomUserDetailsServiceImpl userDetailsService;
    private final JwtTokenProvider jwtTokenProvider;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader(AUTHORIZATION_HEADER);

        String username = null;
        String jwtToken = null;

        // JWT Token is in the form "Bearer token". Remove Bearer word and get only the Token
        if (requestTokenHeader != null && requestTokenHeader.startsWith(BEARER_PREFIX)) {
            try {
                jwtToken = requestTokenHeader.substring(7);
                Claims claims = jwtTokenProvider.getUsernameFromToken(jwtToken, request);
                username = claims.getSubject();
                String nickname = (String) claims.get("nickname");
                log.info("유저 인덱스 = {}  유저 닉네임 = {} ", username, nickname);
            } catch (NullPointerException e) {
                log.info("로그인 실패");
            }
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            // 토큰이 유효한 경우.. 수동으로 인증을 설정하도록 Spring Security를 구성
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            usernamePasswordAuthenticationToken
                    .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            // 컨텍스트에서 인증을 설정한 후, 현재 사용자가 인증되었음을 지정. Spring Security Configurations 성공적으로 통과.
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
        chain.doFilter(request, response);
    }
}

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        // 403 권한 거부 에러를 뱉는다.
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tripcoach.core.common.apiresult.dto.ApiResult;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import java.io.IOException;
import java.io.PrintWriter;

import static com.tripcoach.core.common.apiresult.comcode.ComCode.AUTH_FAIL_CODE;
import static com.tripcoach.core.common.apiresult.comcode.ComCode.LOGIN_FAIL;
import static com.tripcoach.core.common.apiresult.util.ApiUtils.error;


public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        ApiResult<?> error = error(null, LOGIN_FAIL, AUTH_FAIL_CODE);

        // Convert the DTO to a JSON string
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResponse = objectMapper.writeValueAsString(error);

        // Set the content type of the response to JSON
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        // Write the JSON string to the response body
        PrintWriter out = response.getWriter();
        out.print(jsonResponse);
        out.flush();
    }


}
@Slf4j
@RequiredArgsConstructor
@Service
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    private final FlyingDistanceLogService flyingDistanceLogService;

    @Override
    public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException {

        Member member = ((MemberContext) authentication.getPrincipal()).getMember();

        String token = new JwtTokenProvider().generateToken(member);
        LoginRespDto result = new LoginRespDto(member, token);

        ApiResult<LoginRespDto> success = success(result, SUCCESS, SUCCESS_CODE);

        // Convert the DTO to a JSON string
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResponse = objectMapper.writeValueAsString(success);

        // Set the content type of the response to JSON
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");


        // Write the JSON string to the response body
        PrintWriter out = response.getWriter();
        out.print(jsonResponse);
        out.flush();

        // 로그인 성공했을때만 이력을 남김
        flyingDistanceLogService.loginLog(member);
    }
}
정수원님의 프로필 이미지
정수원
지식공유자

깃허브에서 받을 수 없나요

환경설정이나 실행에 필요한 코드 모두 필요합니다

김준엽님의 프로필 이미지
김준엽
질문자

회사 프로젝트여서 코드를 전체 드리기가 어려운점 이해부탁드리겠습니다 ㅠ

김준엽님의 프로필 이미지
김준엽
질문자

제가 이코드로 실행될수있게끔 프로젝트를 다시만들어서 공유드리겠습니다

 감사합니다

김준엽님의 프로필 이미지
김준엽

작성한 질문수

질문하기