티스토리 뷰

회사에서 추가적으로 로그인에 관한 추가요구사항이 내려왔습니다.

 

비밀번호에 BCrypt 만 적용하면 될 줄 알았는데 짧은 시간내에 여러가지 기능을 덧붙여야한다고 하네요..

 

시스템 보안정검이 있어서 증적예시가 필요한 부분입니다.. 

 

1) 접속 시 로그인 실패 횟수 제한 설정(5회 이하)이 적용되어 있는가?

 - 로그인 실패 5회 후 계정이 잠기거나 접속을 차단된 화면 스크린샷을 증적으로 제시한 경우 양호

 - 로그인 실패 횟수 제한 설정 화면 또는 실제 5회 실패 시 접근이 차단되는 화면

 

2) 동일 사용자의 동시 접속을 제한하고 있는가?

 - 동시접속이 제한되는것을 확인가능한 경우 양호

( 이경우 Spring Security의 maxSession 을 1로 잡아두어 어느정도 해결이 가능하지만 추가 커스터마이징을 통해 Alert() 창과 기존의 로그인한 세션을 만료시키고 새로운 세션을 생성하는 기능을 개발함)

 

하여간 말이죠

로그인은 SpringSecurity가 관여하고 있기 때문에 코드를 조금 손을 대버렸슴니다

저는 코린이가  SpringSecurity 관련 코드를 손대면 무서워용..

 

로그인시에 

CustomAuthenticationFailureHandler 와 CustomAuthenticationSuccessHandler  를 거치게 되는데용

CustomAuthenticationFailureHandler 에 아래코드를 추가해주었습니당

 

 

if(exception instanceof BadCredentialsException) {
            userRepository.findByUsername(username).ifPresent(user -> {
                user.setFailCount(user.getFailCount() + 1); // 실패 횟수 증가

                if (user.getFailCount() >= 5) { // 예: 최대 5번 허용
                    user.setEnabled(false);// 계정 잠금
                }
                userRepository.save(user); // 변경 사항 저장
            });
            errMsg = "Invalid Username or Password";
        } else if(exception instanceof DisabledException) {
            errMsg = "Locked";
        }
}

이렇게만 하면 될 줄 알았어여

 

아니나 글쎄 근데 이미 제가 위에서 body를 읽었는데 다시 읽으려니까 

IOException이 뜨는거에요./..

 

 

 

그래서 추가로 CachedBodyHttpServletRequest 를 구현했습니다.. (ChatGPT의 도움을 받아..)

 

어찌저찌 해결을 해서 짜자잔 다른 api 호출을 해보니... ;;

 

java.lang.IllegalStateException: getReader() has already been called for this request

 

이 오류가 떴어요.. 저 진짜 침울...

GPT야 도와줘.....

 

ㅠㅠ 3번은 해당사항없고 (이미 @RequestBody를 통해 dto를 받고 있었음)

1, 2번 인거같아서 도움을 받아서 body 캐싱을 진행했습니다 ..

 

 

 

public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
    private final String body;
    public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        try (BufferedReader bufferedReader = request.getReader()) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        }
        this.body = stringBuilder.toString();
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new StringReader(body));
    }

    @Override
    public ServletInputStream getInputStream() {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return byteArrayInputStream.available() == 0;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener listener) {
                throw new UnsupportedOperationException();
            }
        };
    }

    public String getBody() {
        return body;
    }



}

 

결론은 api 호출에도 아무런 문제 없고!!

 

모든 기능에 동작없는 CachedBodyHttpServletRequest 를 작성하였습니다 ㅠ_ㅠ 

기나긴 여정...

 

감사합니당 ~ ~ 

더 좋은 코드가 있다면 댓글로 말씀해주세용 !!