본문 바로가기
web/Bakery Shop Project

쇼핑몰 구현 16 - Handler

by su0a 2024. 2. 23.

1. GlobalExceptionHandler

@ControllerAdvice
public class GlobalExceptionHandler {

    //재고부족 예외처리
    @ExceptionHandler(NotEnoughStockException.class)
    public String handleNotEnoughStockException(NotEnoughStockException e, Model model){
        model.addAttribute("message","재고수량보다 주문수량이 많습니다.");
        model.addAttribute("nextUrl","/");
        return "printMessage";
    }

    //해당 상품 존재하지 않을 때 사용
    @ExceptionHandler(EntityNotFoundException.class)
    public String handleEntityNotFoundException(EntityNotFoundException e,Model model){
        model.addAttribute("message","상품이 존재하지 않습니다.");
        model.addAttribute("nextUrl","/items");
        return "printMessage";
    }
}

 

2. MyAccessDeniedHandler

@AllArgsConstructor
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    private final MemberRepository memberRepository;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Member loginMember = null;
        if(auth !=null){
            loginMember = memberRepository.findByEmail(auth.getName()).get();
        }
        String requestURI = request.getRequestURI();

        //로그인한 유저가 login, join을 시도한 경우
        if(requestURI.contains("/members/login")||requestURI.contains("/members/join")){
            //메세지 출력 후 홈으로 redirect
            response.setContentType("text/html");
            PrintWriter pw = response.getWriter();
            pw.println("<script>alert('이미 로그인 되어있습니다!'); location.href='/';</script>");
            pw.flush();
        }

        //ADMIN이 아닌데 관리자 페이지에 접속한 경우
        else if(requestURI.contains("admin")){
            //메세지 출력 후 홈으로 redirect
            response.setContentType("text/html");
            PrintWriter pw = response.getWriter();
            pw.println("<script>alert('관리자만 접속 가능합니다!'); location.href='/';</script>");
            pw.flush();
        }
    }
}

 

3. MyAuthendticationEntryPoint

public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {

    //인증하지 않은 유저가 특정 url에 접근했을 경우
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        //메세지 출력 후 홈으로 redirect
        response.setContentType("text/html");
        PrintWriter pw = response.getWriter();
        pw.println("<script>alert('로그인한 멤버만 가능합니다!'); location.href='/members/login';</script>");
        pw.flush();
    }
}

 

4. MyLoginSuccessHandler

@AllArgsConstructor
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
    private final MemberRepository memberRepository;

    //로그인 성공시 발생하는 핸들러
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //세션 유지 시간 = 3600초
        HttpSession session = request.getSession();
        session.setMaxInactiveInterval(3600);

        Member loginMember = memberRepository.findByEmail(authentication.getName()).get();

        //성공 시 메세지 출력 후 홈 화면으로 redirect
        response.setContentType("text/html");
        PrintWriter pw = response.getWriter();
        String prevPage = (String) request.getSession().getAttribute("prevPage");
        if(prevPage!=null){
            pw.println("<script>alert('"+loginMember.getName()+"님 반갑습니다!'); location.href='" + prevPage + "';</script>");
        } else{
            pw.println("<script>alert('" + loginMember.getName() + "님 반갑습니다!'); location.href='/';</script>");
        }

        pw.flush();
    }
}

 

5. MyLogoutSuccessHandler

public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    //로그아웃 시 사용되는 핸들러
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<script>alert('로그아웃 되었습니다.'); location.href='/';</script>");
        out.flush();
    }
}

 

6. UserDetail

// Spring Security가 로그인 요청을 가로채서 로그인 진행
// 로그인에 성공하면 Spring Security의 고유한 세션에 UserDetails 타입의 Object로 저장
@Getter
public class UserDetail implements UserDetails {

    private Member member;

    public UserDetail(Member member) {
        this.member = member;
    }

    // 계정이 가지고 있는 권한 목록 return
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new ArrayList<>();
        collection.add(() -> {
            return member.getMembership().toString();
        });
        return collection;
    }

    @Override
    public String getPassword() {
        return member.getPassword();
    }

    @Override
    public String getUsername() {
        return member.getEmail();
    }

    // 계정이 만료되었는지 (true: 만료 X)
    @Override
    public boolean isAccountNonExpired() { return true; }

    // 계정이 잠겼는지 (true : 잠김 X)
    @Override
    public boolean isAccountNonLocked() { return true; }

    // 비밀번호가 만료되었는지 (ture: 만료 X)
    @Override
    public boolean isCredentialsNonExpired() { return true; }

    // 계정이 활성화(사용 가능)인지 (true: 활성화)
    @Override
    public boolean isEnabled() { return true; }
}

 

7. UserDetailService

//spring security 에서 유저 정보 가져오기 위해 사용되는 service
@Service
@RequiredArgsConstructor
public class UserDetailService implements UserDetailsService {

    private final MemberRepository memberRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Member member = memberRepository.findByEmail(username)
                .orElseThrow(() -> {
                    return new UsernameNotFoundException("해당 유저를 찾을 수 없습니다.");
                });

        // Security의 세션에 유저 정보가 저장됨
        return new UserDetail(member);
    }
}