항해99/개발일지

20220214 개발일지 #Spring security 아키텍처 공부하기

paran21 2022. 2. 14. 23:52

현재 로그인은 기본적으로 controller에 구현되어 있고(로직들이 controller에 너무 많이 들어가 있는 것 같아서 서비스에서 구현되도록 리팩토링했다.), 아마 authenticationManager가 인증하면서 코드에는 보이지 않지만 AuthenticationProvider ~ DB에서 User를 찾아서 UserDetails에 담아 리턴하는 것까지 이루어지는 것 같다.

여기서도 보면 UsernamePasswordAuthenticationFilter를 통해 Authentication Manager로 연결되고 이후 로직들이 처리되는 것을 볼 수 있다. (참고자료: https://webfirewood.tistory.com/115)

formLogin을 Disable한 상태고 별도로 Filter를 커스텀하지 않았기 때문에 Authentication SuccessHandler나 Authentication FailureHandler는 사용할 수 없는 상태다.(물론 방법을 못 찾았을 수도 있다.)

 

로그인 실패 시 처리와 로그인이 필요한 페이지에 접근하는 경우를 처리하기 위해 AuthenticationEntryPoint를 구현하는 객체를 만들었다.

처음에는 로그인이 필요한 경우 로그인 페이지로 redirect시켰는데, 로그인 비즈니스 로직에서 로그인 실패를 구현하는 중에 로그인 실패시 무조건 이 EntryPoint 객체가 실행되는 걸 확인하였다.

그래서 이 객체를 수정해서, 로그인 창에서 AuthenticationException이 발생하면 로그인 실패로, 인증이 필요한 경우에는 로그인을 하라는 메시지를 출력하는 것으로 수정하였다.

 

처음에는 throw new ~Exception을 통해 ExceptionHandler로 처리하려고 하였는데 security 부분이 적용되지 않는 것 같다. 

그래서 다른 에러 처리와 동일한 형태로 출력되게 맞춰주었다.

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(
            HttpServletRequest request,
            HttpServletResponse response,
            AuthenticationException authException
    ) throws IOException, ServletException {

        String requestUri = request.getRequestURI();

        // 로그인 창에서 AuthenticationException 발생시
        if(requestUri.contains("/user/login")) {
            // 400 에러로 지정
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            // json 리턴 및 한글깨짐 수정.
            response.setContentType("application/json;charset=utf-8");
            JSONObject json = new JSONObject();
            String message = "아이디 또는 비밀번호를 확인해주세요.";
            json.put("httpStatus", HttpStatus.BAD_REQUEST);
            json.put("errorMessage", message);

            PrintWriter out = response.getWriter();
            out.print(json);
        } else { // 로그인이 필요한 창에 접근시시            // 401 에러로 지정
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            // json 리턴 및 한글깨짐 수정.
            response.setContentType("application/json;charset=utf-8");
            JSONObject json = new JSONObject();
            String message = "로그인 후 이용해주세요.";
            json.put("httpStatus", HttpStatus.UNAUTHORIZED);
            json.put("errorMessage", message);

            PrintWriter out = response.getWriter();
            out.print(json);
        }

 

저녁에 진행한 전체회의에서는 프론트와 연결시켜 몇 가지 테스트해보았다.

일부 문제가 확인되었지만 전반적으로는 잘 동작하는 것 같다.

중간 멘토링 때 JWT도 해보라는 조언을 받았는데, 며칠동안 시큐리티 하면서 너무 지쳐서 약간 충전이 필요할 것 같다.

JPA도 좀 봐야해서 일단 머리 좀 식히고 보면 될 것 같다.

그래서 세션하면서 security 아키텍처도 약간 눈에 익어서 구현 자체는 아주 어려울 것 같지는 않은데 실제로 해보면 또 어떨지 모르겠다.