BE전문가 프로젝트

5-3 Authorization(인가) - AuthorizationFilter 생성 본문

SpringBoot Security

5-3 Authorization(인가) - AuthorizationFilter 생성

원호보고서 2023. 7. 11. 23:31

JwtAuthorizationFilter

/**
 * @package com.amount.amount.config.security.jwt
 * @class   JwtAuthorizationFilter
 * @brief   인가
 * @details 권한이나 인증이 필요한 특정 주소를 요청했을 때 BasicAuthenticationFilter를 탄다.
 *          권한이나 인증이 필요하지 않타면 로직 활용 x
 * @author  최원호
 * @date    2023.05.02
 * version  1.0
 */
@Slf4j
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    private final JwtService jwtService;

    public JwtAuthorizationFilter(AuthenticationManager authenticationManager, JwtService jwtService) {
        super(authenticationManager);
        this.jwtService = jwtService;
    }

    /**
     * @brief  인가
     * @param req
     * @param res
     * @param chain
     * @detail 인증이나 권한이 필요한 주소 요청 시 필터로 이동
     */
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        try {

            //올바르지 않은 헤더 재로그인
            if (jwtService.isValidHeaderOrThrow(req)) {

                String accessToken = jwtService.replaceAccessToken(req);
                String refreshToken = jwtService.replaceRefreshToken(req);

                // 만료된 리프레쉬 토큰은 재로그인 필요
                if (jwtService.isNotExpiredRefreshToken(refreshToken)) {

                    LoginResponseDto userDto = jwtService.selectByRefreshToken(refreshToken);

                    // 엑세스 토큰이 만료된 경우 새로
                    if (!jwtService.isNotExpiredAccessToken(accessToken)) {

                        log.info("The Token had been expired");

                        String reissuedAccessToken = jwtService.createAccessToken(userDto.getEmail());
                        jwtService.setAccessTokenToHeader(res, reissuedAccessToken);
                    }

                    // 리프레쉬 토큰이 10일 이내 만료일 경우 새로 발급
                    if (jwtService.checkTokenIsMadeInTendays(refreshToken)) {

                        log.info("** It has been 10 days since token was made **");

                        refreshToken = jwtService.updateRefreshToken(userDto.getEmail(), refreshToken);
                        jwtService.setRefreshTokenToHeader(res, refreshToken);
                    }

                    PrincipalDetails principal = new PrincipalDetails(userDto);

                    Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());

                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }

            } else {
                log.info("[LOGIN] > 재 로그인 필요");
            }
        } catch (AuthorizationServiceException e){
            log.info("******************************************************************");
            log.info("인가 에러>>>>>>>>>>>>>>>>>>"+e.getMessage());
            log.info("******************************************************************");
            req.setAttribute(JwtProperties.Exception, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }

        chain.doFilter(req, res);
    }
}
 

프로세스

#1 토큰 정상 여부 확인

  1. 헤더의 토큰 여부를 확인하고 인증방식이 Bearer인지 확인한다.
  2. RefreshToken이 정상적인 토큰인가를 시크릿 키를 이용하여 확인한다.
  3. AccessToken이 정상적인 토큰인가를 시크릿 키를 이용하여 확인한다.
  4. RefreshToken이 10일 이내에 발급된 토큰인가를 확인한다.

#2  UserDetails 객체 생성

#3  Authentication 객체가 저장되는 보관소 즉 SecurityContextHolder에 객체를 저장한다.

Comments