Skip to content

Commit e2bf3c7

Browse files
committed
CLAP-109 Feat: 로그인 실패를 관리하고 계정 잠금 상태를 확인하는 LoginAttemptFilter 구현
<footer> - 관련: #59
1 parent 3773dfd commit e2bf3c7

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package clap.server.adapter.inbound.security;
2+
3+
import clap.server.application.service.auth.LoginAttemptService;
4+
import clap.server.exception.AuthException;
5+
import clap.server.exception.code.CommonErrorCode;
6+
import jakarta.servlet.FilterChain;
7+
import jakarta.servlet.ServletException;
8+
import jakarta.servlet.http.HttpServletRequest;
9+
import jakarta.servlet.http.HttpServletResponse;
10+
import lombok.RequiredArgsConstructor;
11+
import lombok.extern.slf4j.Slf4j;
12+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
13+
import org.springframework.security.core.context.SecurityContextHolder;
14+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
15+
import org.springframework.web.filter.OncePerRequestFilter;
16+
17+
import java.io.IOException;
18+
import java.util.ArrayList;
19+
20+
import static clap.server.common.constants.AuthConstants.SESSION_ID;
21+
22+
23+
@RequiredArgsConstructor
24+
@Slf4j
25+
public class LoginAttemptFilter extends OncePerRequestFilter {
26+
27+
private static final String LOGIN_ENDPOINT = "/api/auths/login";
28+
private final LoginAttemptService loginAttemptService;
29+
30+
@Override
31+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
32+
throws ServletException, IOException {
33+
34+
String sessionId = request.getHeader(SESSION_ID.getValue().toLowerCase());
35+
36+
if (request.getRequestURI().equals(LOGIN_ENDPOINT)) {
37+
if (sessionId == null) {
38+
throw new AuthException(CommonErrorCode.BAD_REQUEST);
39+
}
40+
loginAttemptService.checkAccountIsLocked(sessionId);
41+
}
42+
43+
UsernamePasswordAuthenticationToken authenticationToken =
44+
new UsernamePasswordAuthenticationToken("user", null, new ArrayList<>());
45+
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
46+
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
47+
48+
filterChain.doFilter(request, response);
49+
}
50+
51+
}

src/main/java/clap/server/adapter/inbound/security/SecurityUserDetails.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static UserDetails from(MemberEntity member) {
5252
.userId(member.getMemberId())
5353
.username(member.getName())
5454
.authorities(List.of(new CustomGrantedAuthority(member.getRole().name())))
55-
.accountNonLocked(member.getStatus().equals(MemberStatus.INACTIVE))
55+
.accountNonLocked(member.getStatus().equals(MemberStatus.ACTIVE))
5656
.build();
5757
}
5858

src/main/java/clap/server/common/constants/AuthConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
@Getter
66
public enum AuthConstants {
7-
AUTHORIZATION("Authorization"), TOKEN_PREFIX("Bearer ");
7+
AUTHORIZATION("Authorization"), TOKEN_PREFIX("Bearer "), SESSION_ID("sessionId");
88

99
private final String value;
1010

src/main/java/clap/server/exception/code/AuthErrorCode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ public enum AuthErrorCode implements BaseErrorCode {
2121
FORBIDDEN_ACCESS_TOKEN(HttpStatus.FORBIDDEN, "AUTH_012","해당 토큰에는 엑세스 권한이 없습니다."),
2222
INVALID_TOKEN(HttpStatus.UNAUTHORIZED,"AUTH_013", "유효하지 않은 토큰입니다."),
2323
REFRESH_TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "AUTH_014", "리프레시 토큰을 찾을 수 없습니다."),
24-
REFRESH_TOKEN_MISMATCHED(HttpStatus.UNAUTHORIZED, "AUTH_014", "리프레시 토큰이 일치하지 않습니다");
24+
REFRESH_TOKEN_MISMATCHED(HttpStatus.UNAUTHORIZED, "AUTH_014", "리프레시 토큰이 일치하지 않습니다"),
25+
ACCOUNT_IS_LOCKED(HttpStatus.UNAUTHORIZED, "AUTH_015", "접근할 수 없는 계정입니다."),
26+
LOGIN_REQUEST_FAILED(HttpStatus.UNAUTHORIZED, "AUTH_016", "로그인에 실패하였습니다.")
27+
;
2528

2629
private final HttpStatus httpStatus;
2730
private final String customCode;

0 commit comments

Comments
 (0)