1. 동작 원리Spring Security 의존성이 없는 경우 'HTTP 요청 → WAS → 필터 → 서블릿 → 컨트롤러' 순으로 작동한다. 그림으로 표현하면 다음과 같다.반면에, Spring Security 의존성을 추가하면 필터를 하나 추가하여 중간에 요청을 가로챈다. 가로채진 요청은 Spring Security 로직을 마친 후 다음 필터로 복귀한다.DelegatingFilterProxy: Bean Filter를 찾아 해당 필터로 요청을 넘긴다. (FilterChainProxy가 없다면 Bean Filter들을 DelegatingFilterProxy에 하나하나 등록해야 한다.)FilterChainProxy: Spring Security가 제공하는 특별한 Bean Filter다. 우리는 이 Filter..
BackEnd
1. 의존성 프로젝트에 사용한 의존성은 다음과 같다.dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-mustache' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connect..
1. JWT의 의미와 구성JWT란 Json Web Token의 약자로 사용자 인증에 사용되는 토큰이다. JWT의 구조는 다음과 같이 Header, Payload, Signature로 이루어진다.1.1. Header첫 번째로 Header는 typ과 alg 두 가지 정보로 구성된다. typ은 토큰의 타입을 말한다. 우리는 JWT를 사용하므로 현재 typ은 JWT가 된다. alg는 Signature를 해싱하기 위한 알고리즘을 말한다. RSA, SHA 256 등이 있다. 즉, 아래와 같이 작성된다.{ "alg": "HS256", "typ": "JWT"}1.2. Payload두 번째로 Payload는 토큰의 정보가 들어있다. 이때 이 정보들 하나하나 각각을 Claim이라고 부른다. (Key-Value ..
1. 서블릿 예외 처리서블릿은 2가지 방식으로 예외를 처리한다.1.1. Exception웹 애플리케이션은 사용자 요청별로 스레드가 할당되고, 서블릿 컨테이너 안에서 실행된다. 애플리케이션에서 예외가 발생했는데 해당 예외를 잡지 못한 경우는 어떻게 될까? 기본적으로 어떠한 요청이 들어올 경우 다음과 같이 요청이 전파된다.WAS → 필터 → 서블릿 → 인터셉터 → 컨트롤러만약 컨트롤러에서 예외가 발생하면 요청의 전파 방향과 반대로 전파된다.WAS ← 필터 ← 서블릿 ← 인터셉터 ← 컨트롤러예외 발생시 서블릿 컨테이너에서 그에 맞는 오류 페이지를 보여준다.1.2. response.sendError() 메서드오류가 발생하면 HttpServletResponse가 제공하는 sendError 메서드를 사용해도 된다...
1. 서블릿 필터이전 포스팅에서 구현한 코드는 로그인을 하지 않아도 특정 url을 입력하면 해당 url로 이동할 수 있다. 이를 위해 모든 비지니스 로직을 수행할 때 사용자의 로그인 여부를 체크할 수 있다. 하지만 이런 방식은 이후 로그인 관련 로직을 바꿀 때 해당 체크 로직을 다 수정해야할 수도 있다.이와 같이 여러 로직에서 공통으로 관심있는 것을 공통 관심사(cross-cutting concern)이라고 한다.이러한 공통 관심사는 AOP로도 해결할 수 있다. 하지만 웹과 관련된 공통 관심사는 서블릿 필터 혹은 스프링 인터셉터를 사용하는 것이 좋다. 필터는 서블릿이 지원하는 수문장 역할을 하는 것으로 필터의 흐름은 다음과 같다.HTTP 요청 → WAS → 필터 → 서블릿 → 컨트롤러만약 필터를 통해 적..
1. 쿠키 사용로그인 상태를 유지하기 위해서는 쿠키를 사용할 수 있다. 서버에서 로그인에 성공하면 HTTP 응답에 쿠키를 담아서 전달하고, 브라우저는 앞으로 해당 쿠키를 지속적으로 보내면 된다. 쿠키의 종류는 다음과 같다.영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지된다.세션 쿠키: 만료 날짜를 생략하면 브라우저 종류시까지만 유지된다.우리는 세션 쿠키를 사용해볼 것이다. 쿠키는 다음과 같이 response에 담을 수 있다.@PostMapping("/login")public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) { ... ..
1. Bean Validation이전 포스팅의 Validation 코드들을 보면, reject, rejectValue 등의 메소드를 활용해 검증을 수행했다. 하지만 이런 코드들은 너무 번거롭다. 하지만 특정 필드의 검증 로직은 대부분 빈 값인지, 특정 범위 안에 있는지 등 일반적인 것들을 목표로 한다. Bean Validation은 이러한 공통된 일반적인 검증 로직들을 @NotBlank, @Range, @Max 등의 어노테이션으로 제공한다.Bean Validation이란 검증 로직을 모든 프로젝트에 적용할 수 있도록 공통화/표준화한 것이다.사실 Bean Validation은 기술 표준(인터페이스)으로 구현체가 따로 있는데, 주로 사용하는 구현체는 하이버네이트 Validator이다. (JPA라는 표준 기술..
1. 검증 직접 처리사용자가 잘못된 값을 입력했는지, 입력하지 않은 값은 없는지를 체크하기 위해서는 검증을 수행해야한다. 검증을 위해 전달된 값들이 우리가 원하는 의도된 값인지 아래와 같이 각각 직접 확인해줄 수 있다.@PostMapping("/add")public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes, Model model) { // 검증 오류 결과를 보관 Map errors = new HashMap(); if (!StringUtils.hasText(item.getItemName())) { errors.put("itemName", "상품 이름은 필수입니다."); }..