71일차 (1) - Spring, JavaScript (내가 쓴 글만 삭제하는 인터셉터, 에러 페이지 처리, 자동 로그인)

Yohan·2024년 6월 3일
0

코딩기록

목록 보기
108/156
post-custom-banner

내가 쓴 글만 삭제하는 인터셉터와 에러 페이지 처리

BoardInterceptor

  • 관리자이거나 본인일경우에만 글 삭제가 가능하도록함
  • 본인이 아닐 경우 에러 페이지를 반환하도록 함
public class BoardInterceptor implements HandlerInterceptor {

    private final BoardMapper boardMapper;

    // preHandle을 구현하여
    // 로그인을 안한 회원은 글쓰기, 글수정, 글삭제 요청을 거부할 것!
    // 거부하고 로그인 페이지로 리다이렉션할 것!
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HttpSession session = request.getSession();

        // 요청 URL
        String redirectUri = request.getRequestURI();

        ////////////// 로그인이 안됐다면? //////////////
        if (!isLoggedIn(session)) {
            log.info("origin: {}", redirectUri);
            response.sendRedirect("/members/sign-in?message=login-required&redirect=" + redirectUri);
            return false;
        }

        ////////////// 로그인이 되었다면? //////////////
        // 삭제요청이 들어오면 서버에서 한번더 관리자인지? 자기가쓴글인지 체크
        // 관리자인가?
        if (isAdmin(session)) {
            return true;
        }

        // 삭제요청인지?
        if (redirectUri.equals("/board/delete")) {
            // 내가 쓴 글이 아닌지??
            // 현재 삭제하려는 글의 글쓴이 계정명과
            // -> DB에서 조회해보면 됨 -> 글번호가 필요함
            int bno = Integer.parseInt(request.getParameter("bno"));
            Board board = boardMapper.findOne(bno);
            String boardAccount = board.getAccount();

            // 현재 로그인한 회원의 계정명을 구해
            String loggedInUserAccount = getLoggedInUserAccount(session);

            // 본인이 아니라면 에러 페이지 반환
            if (!isMine(boardAccount, loggedInUserAccount)) {
                response.sendRedirect("/access-deny?message=authorization");
                return false;
            }

        }
        return true;
    }
}

BoardController

  • /board/delete?bno=숫자 처럼 읽을 수 있게 bno를 읽는다.

ErrorPageConfig

  • 에러페이지에 대한 설정, 404와 500 에러에 대해 설정했다.
// 미리 만들어놓은 에러페이지로 안내해주는 설정
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");

        registry.addErrorPages(errorPage404, errorPage500);
    }
}

ErrorController

  • 에러 페이지를 반환해준다.
@Controller
public class ErrorController {

    @GetMapping("/error/404")
    public String error404() {
        return "error/error404";
    }
    @GetMapping("/error/500")
    public String error500(String message, Model model) {
        model.addAttribute("msg", message);
        return "error/access-deny";
    }
}

error.jsp

  • 삭제시 본인이 아닐 경우와 404, 500 에러에 대한 페이지

자동 로그인

쿠키 생성

  • 자동로그인 요청 - 쿠키생성 - 쿠키 값을 db에 저장, 클라이언트에 저장
    • 쿠키를 서버에도 기록하고 DB에도 저장해야한다.
  • 자동 로그인을 위해 Member 테이블에 쿠키에 저장한 값과 만료시간에 대한 컬럼을 추가

쿠키 사용

MemberMapper.java

AutoLoginDto

  • 자동로그인을 요청할 때 필요한 것들 포장하는 객체
public class AutoLoginDto {

    private String sessionId; // 자동로그인 쿠키값
    private LocalDateTime limitTime; // 만료시간
    private String account; // 계정명

}

MemberMapper.xml

  • MemberService
  • 로그인 검정시 자동로그인기능 추가 처리
    • 쿠키를 생성하여 클라이언트와 DB에 쿠키값을 저장!
// 자동로그인 추가 처리
        if (dto.isAutoLogin()) {
            // 1. 자동 로그인 쿠키 생성
            // - 쿠키 내부에 절대로 중복되지 않는 유니크한 값을 저장
            //   (UUID, SessionID)
            String sessionId = session.getId();
            // "auto" 상태, sessionId 필요
            Cookie autoLoginCookie = new Cookie(AUTO_LOGIN_COOKIE, sessionId);
            // 쿠키 설정
            autoLoginCookie.setPath("/"); // 쿠키를 사용할 경로
            autoLoginCookie.setMaxAge(60 * 60 * 24 * 90); // 자동로그인 유지 시간

            // 2. 쿠키를 클라이언트에 전송 - 응답바디에 실어보내야 함
            response.addCookie(autoLoginCookie);

            // 3. DB에도 해당 쿠키값을 저장
            memberMapper.updateAutoLogin(
                    AutoLoginDto.builder()
                            .sessionId(sessionId)
                            .limitTime(LocalDateTime.now().plusDays(90))
                            .account(account)
                            .build()
            );
        }


        maintainLoginState(session, foundMember);

        return SUCCESS;

쿠키가 서버에 기록된 것 확인가능

쿠키가 DB에도 기록된 것 확인가능

여기까지 진행했을 때 껐다켜도 로그인이 유지되는 문제가 발생 -> 로그 아웃 처리 필요!

자동로그인 인터셉터 생성

Member

  • DB와 1대1 매칭되는 객체이기 때문에 sessionId와 limitTime추가

MemberMapper

  • 세션 아이디로 회원의 정보를 조회하는 메서드 추가
    • 자동로그인할 때 세션 아이디로 회원 정보가 조회되었다는 것은 쿠키값이 있다는 것이므로 자동로그인이 가능

MemberMapper.xml

AutoLoginInterceptor

  • 세션 아이디(쿠키값)로 회원 정보를 조회했을 때 있다면 자동 로그인 처리 수행
@Configuration
@RequiredArgsConstructor
public class AutoLoginInterceptor implements HandlerInterceptor {

    private final MemberMapper memberMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 1. 사이트에 들어오면 자동로그인 쿠키를 가지고 있는지 확인
        Cookie autoLoginCookie = WebUtils.getCookie(request, LoginUtil.AUTO_LOGIN_COOKIE);

        // 2. 자동로그인 쿠키가 있으면 사이트 로그인 처리를 수행
        if (autoLoginCookie != null) {
            // 3. 쿠키에 들어있는 랜덤값을 읽기
            String sessionId = autoLoginCookie.getValue();

            // 4. 세션아이디로 회원정보 조회
            Member foundMember = memberMapper.findMemberBySessionId(sessionId);

            // 5. 회원이 정상조회되었고 자동로그인 만료시간 이전이라면
            //    사이트 로그인 처리(세션에 DTO세팅)를 수행
            if (foundMember != null && LocalDateTime.now().isBefore(foundMember.getLimitTime())) {

                MemberService.maintainLoginState(request.getSession(), foundMember);
            }
        }
        return true;
    }
}

InterceptorConfig

  • config에 인터셉터 등록

로그아웃 처리

MemberController

  • 로그아웃 부분에 자동로그인일 경우 쿠키제거, db에도 세션 아이디, 만료시간를 원래대로 되돌려놓음

MemberService

// 자동로그인 관련데이터를 원래대로 바꿔놓기
    public void autoLoginClear(HttpServletRequest request, HttpServletResponse response) {

        // 1. 쿠키 제거하기
        Cookie c = WebUtils.getCookie(request, AUTO_LOGIN_COOKIE);
        if (c != null) {
            c.setPath("/");
            c.setMaxAge(0); // 쿠키수명을 0으로 설정하고 보내면 사라짐
            response.addCookie(c);
        }

        // 2. DB에 자동로그인 컬럼들을 원래대로 돌려놓음
        memberMapper.updateAutoLogin(
                AutoLoginDto.builder()
                        .sessionId("none")
                        .limitTime(LocalDateTime.now())
                        .account(LoginUtil.getLoggedInUserAccount(request.getSession()))
                        .build()
        );
    }
profile
백엔드 개발자
post-custom-banner

0개의 댓글