@@ -0,0 +1,79 @@
+package nextstep.security.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import nextstep.security.authentication.Authentication;
+import nextstep.security.authentication.AuthenticationManager;
+import nextstep.security.core.context.SecurityContext;
+import nextstep.security.core.context.SecurityContextHolder;
+import nextstep.security.exception.AuthenticationException;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+public abstract class AbstractAuthProcessingFilter extends OncePerRequestFilter {
+    private final AuthenticationManager authenticationManager;
+
+    protected AbstractAuthProcessingFilter(final AuthenticationManager authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    @Override
+    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
+        if (!match(request)) {
+            filterChain.doFilter(request, response);
+            return;
+        }
+
+        if (isAlreadyAuthenticated()) {
+            filterChain.doFilter(request, response);
+            return;
+        }
+
+        Authentication authRequest = makeAuthentication(request);
+
+        Authentication authentication = authenticate(authRequest);
+
+        saveAuthentication(request, response, authentication);
+
+        successAuthentication(request, response, filterChain);
+
+        if (!shouldContinueFilterChain()) {
+            return;
+        }
+
+        doFilter(request, response, filterChain);
+    }
+
+    private static boolean isAlreadyAuthenticated() {
+        return SecurityContextHolder.getContext().getAuthentication() != null;
+    }
+
+    private Authentication authenticate(final Authentication authRequest) {
+        Authentication authentication = this.authenticationManager.authenticate(authRequest);
+        if (!authentication.isAuthenticated()) {
+            throw new AuthenticationException();
+        }
+
+        return authentication;
+    }
+
+    abstract boolean match(final HttpServletRequest request);
+
+    private void saveAuthentication(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) {
+        SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
+        securityContext.setAuthentication(authentication);
+        SecurityContextHolder.setContext(securityContext);
+    }
+
+    abstract Authentication makeAuthentication(final HttpServletRequest request);
+
+    protected abstract void successAuthentication(final HttpServletRequest request, final HttpServletResponse response,
+                                                  final FilterChain filterChain) throws ServletException, IOException;
+
+    protected boolean shouldContinueFilterChain() {
+        return true;
+    }
+}

리뷰: 재연님! 
제가 작성한 BasicAuthFilter와 FormAuthFilter는 security 의 UsernamePasswordAuthenticationFilter와 BasicAuthenticationFilter를 참고하여 작성하였는데요. 

form요청의 경우 'login '요청에 대해서만 필터가 작동하고 인증이 성공 했을때 해당 filter에서 응답을 반환하고
Basic요청의 경우 유효한 Authorization 헤더가 있는 경우 인증을 성공해도  filterchain의 doFilter를 호출 하는것으로 봐서

두 필터간의 filterChain.doFilter()의 동작 유무의 차이가 있다고 생각해서 추상 클래스 AbstractAuthProcessingFilter의 successAuthentication() 에 각각 다르게 doFilter()를 호출하게 햇습니다! 

혹시 제가 틀리게 판단한 부분이 있으면 말씀부탁드립니다!