interceptor, security 설정

jinvicky·5일 전
0

Next.js

목록 보기
2/2

Intro


로그인 개발하고 싶다면 interceptor를 꼭 사용하게 된다.
spring boot는 interceptor, next.js는 middleware가 있다.
우리는 비밀번호를 인코딩해서 저장해야 하기 때문에 spring security도 필요하고, 그냥 db 조회하면 db가 뻑 가기 때문에 캐싱과 성능을 위해 redis도 필요하다.

여기에 필요한 설정들 잊지 말고 기억하자!

Next.js middleware

프로젝트당 1개의 middleware.ts 파일을 선언할 수 있으며, 서버 컴포넌트다.

경로 등록

미들웨어가 등록되기를 원하는 경로만을 지정한다.

export const config = {
  matcher: [
    // '/chat/:path*',
    "/my-page/:path*",
    "/user/sign-in",
    "/user/sign-up",
    // '/test/:path*',
  ],
};

쿠키 사용

/next/headers로 쿠키 관련 메서드를 사용할 수 있다.

  • 도메인 제외 현재 경로를 알려면 request.nextUrl.pathname
  • request.nextUrl.clone() 을 사용하면 현재 경로를 객체로 받을 수 있다. (pathname도 여기 포함)

절대 경로

서버 컴포넌트는 url이 절대경로여야 한다.

  • api url 앞에 profile별로 .env.development 등에서 등록한 도메인 url 붙여서 호출해야 한다.
  • redirect할 때도 마찬가지로 new URL()request.url과 함께 감싸주어야 한다.

middleware.ts

import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";

import { cookies } from "next/headers";

export async function middleware(request: NextRequest) {
  const cookieStore = cookies();
  const userSession = cookieStore.get("userSession");
  const currentPath = request.nextUrl.pathname;

  if (userSession === undefined || !userSession?.value) {
    if (currentPath === "/user/sign-in" || currentPath === "/user/sign-up") {
      // 로그인을 안 했는데 로그인/회원가입으로 오면 그냥 통과
      return NextResponse.next();
    }
    // 그외 전부 로그인 페이지로 이동
    return NextResponse.redirect(new URL("/user/sign-in", request.url));
  } else {
    // 로그인을 했는데 로그인/회원가입으로 오면 메인(promotion)으로 보내기
    if (currentPath === "/user/sign-in" || currentPath === "/user/sign-up") {
      return NextResponse.redirect(new URL("/promotion", request.url));
    }
  }
  return NextResponse.next();
}

export const config = {
  matcher: [
    "/my-page/:path*",
    "/user/sign-in",
    "/user/sign-up",
  ],
};

Spring Boot Interceptor

spring boot에서도 특정 경로 요청이 도달하기 전에 체크를 하고 싶다면 인터셉터를 추가한다.

WebConfig의 일부
context-path/api 경로여도 /api 경로를 제외하고 controller 경로 기준으로 등록한다.

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationInterceptor())
                .addPathPatterns("/user/**", "/mypage/**", "/chat/**");
    }

존재하지 않는 api에 대해서는 인터셉터가 핸들링하지 않으니 GlobalControllerAdvice에서 별도 404 예외처리를 해둬야 한다.

/**
* 404 예외 처리
*/
    @ExceptionHandler({NoHandlerFoundException.class})
    public ResponseEntity<ErrorResponse> handleException(NoHandlerFoundException e, WebRequest req) {
        ErrorResponse response = new ErrorResponse(ErrorCode.NOT_FOUND, req);
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }

Spring Security

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-security:3.4.1'

의존성과 config에 passwordEncoder 빈을 등록한다.

@Configuration
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

시큐리티 의존성을 추가하면 무조건 기본 시큐리티 로그인 페이지로 이동하는데 이것을 꺼줘야 한다. exclude 속성에 SecurityAutoConfiguration 클래스를 추가한다.

Application

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
@EnableMongoAuditing
@MapperScan("com.jinvicky.website.mapper") // Mapper가 위치한 패키지 경로
public class KtalkReviewApplication {

    public static void main(String[] args) {
        SpringApplication.run(KtalkReviewApplication.class, args);
    }
}

Outro


jinvicky
Front-End, Back-End Developer / SD Illustrator
✉️ Email: jinvicky@naver.com
💻 Github: https://github.com/jinvicky
🍏 Blog: https://velog.io/@jinvicky/posts
🌟 Website: https://jinvicky.shop

profile
Front-End와 Back-End 경험, 지식을 공유합니다.

0개의 댓글