From c47a63ac32fecbc8c159bbf665a230cafbddd446 Mon Sep 17 00:00:00 2001
From: yang <hc1489@naver.com>
Date: Sun, 16 Jun 2024 17:47:58 +0900
Subject: [PATCH 1/3] =?UTF-8?q?feat:=20AccessDeniedHandler=20=EC=BB=A4?=
 =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../config/jwt/JwtAccessDeniedHandler.java    | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAccessDeniedHandler.java

diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAccessDeniedHandler.java b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAccessDeniedHandler.java
new file mode 100644
index 0000000..4d7ab94
--- /dev/null
+++ b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAccessDeniedHandler.java
@@ -0,0 +1,20 @@
+package com.sanbosillok.sanbosillokserver.config.jwt;
+
+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 JwtAccessDeniedHandler implements AccessDeniedHandler {
+    @Override
+    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
+        response.sendError(HttpServletResponse.SC_FORBIDDEN);
+        response.setContentType("application/json");
+        response.getWriter().write("{\"error\": \"Unauthorized user.\"}");
+    }
+}

From 43df8f75aea01398a7d96b776549c2a797c91f6e Mon Sep 17 00:00:00 2001
From: yang <hc1489@naver.com>
Date: Sun, 16 Jun 2024 17:50:58 +0900
Subject: [PATCH 2/3] =?UTF-8?q?feat:=20AuthenticationEntryPoint=20?=
 =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../jwt/JwtAuthenticationEntryPoint.java      | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAuthenticationEntryPoint.java

diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAuthenticationEntryPoint.java b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAuthenticationEntryPoint.java
new file mode 100644
index 0000000..4ea2808
--- /dev/null
+++ b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtAuthenticationEntryPoint.java
@@ -0,0 +1,21 @@
+package com.sanbosillok.sanbosillokserver.config.jwt;
+
+import io.jsonwebtoken.ExpiredJwtException;
+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.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
+        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        response.setContentType("application/json");
+        response.getWriter().write("{\"error\": \"Please send a valid token.\"}");
+    }
+}

From abae1314cf0ed98765898957c1b6c80e41e874b8 Mon Sep 17 00:00:00 2001
From: yang <hc1489@naver.com>
Date: Sun, 16 Jun 2024 17:51:47 +0900
Subject: [PATCH 3/3] =?UTF-8?q?feat:=20SecurityConfig=EC=97=90=EC=84=9C=20?=
 =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=81=B4=EB=9E=98=EC=8A=A4?=
 =?UTF-8?q?=EB=93=A4=20Bean=20=EB=93=B1=EB=A1=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../config/SecurityConfig.java                | 23 +++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/config/SecurityConfig.java b/src/main/java/com/sanbosillok/sanbosillokserver/config/SecurityConfig.java
index fbd371a..66609e3 100644
--- a/src/main/java/com/sanbosillok/sanbosillokserver/config/SecurityConfig.java
+++ b/src/main/java/com/sanbosillok/sanbosillokserver/config/SecurityConfig.java
@@ -1,9 +1,7 @@
 package com.sanbosillok.sanbosillokserver.config;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.sanbosillok.sanbosillokserver.config.jwt.JwtAuthenticationFilter;
-import com.sanbosillok.sanbosillokserver.config.jwt.JwtTokenProvider;
-import com.sanbosillok.sanbosillokserver.config.jwt.LoginFilter;
+import com.sanbosillok.sanbosillokserver.config.jwt.*;
 import lombok.RequiredArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -60,6 +58,16 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration c
         return configuration.getAuthenticationManager();
     }
 
+    @Bean
+    public JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint() {
+        return new JwtAuthenticationEntryPoint();
+    }
+
+    @Bean
+    public JwtAccessDeniedHandler jwtAccessDeniedHandler() {
+        return new JwtAccessDeniedHandler();
+    }
+
     @Bean
     public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
         http
@@ -82,7 +90,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 
                 //경로별 인가 작업
                 .authorizeHttpRequests((auth) -> auth
-                        .requestMatchers("/signup", "/login", "/checkUserName/{username}", "/image/{fileName}").permitAll()
+                        .requestMatchers("/signup", "/login", "/checkUserName/{username}", "/image/{fileName}", "/token/refresh").permitAll()
                         .requestMatchers(HttpMethod.GET, "/post",  "/post/random", "/post/{title}").hasAnyRole("GUEST", "ACTIVE", "ADMIN")
                         .requestMatchers("/post", "/post/upload", "/post/{title}").hasAnyRole("ACTIVE", "ADMIN")
                         .requestMatchers("/admin", "/admin/{id}").hasRole("ADMIN"))
@@ -91,6 +99,13 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
                 .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtTokenProvider, objectMapper), UsernamePasswordAuthenticationFilter.class)
                 .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), LoginFilter.class)
 
+                // 예외 처리
+                .exceptionHandling(exceptionHandling ->
+                        exceptionHandling
+                                .authenticationEntryPoint(jwtAuthenticationEntryPoint())
+                                .accessDeniedHandler(jwtAccessDeniedHandler())
+                )
+
                 //세션 설정
                 .sessionManagement((session) -> session
                         .sessionCreationPolicy(SessionCreationPolicy.STATELESS));