로그인 한 사용자만 게시판에 들어갈 수 있어야 한다. 앞에서 로그인을 하지 않은 사용자에게는 상품 관리 버튼이 보이지 않기 때문에 문제가 없어 보인다. 그런데 문제는 로그인 하지 않은 사용자도 다음과 같은 http://localhost:8080/board를 직접 호출하면 게시판에 들어갈 수 있다는 점이다. 이를 해결하기 위해 인터셉터를 등록한다.
LoginCheckInterceptor
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("LoginCheckInterceptor 실행!");
HttpSession session = request.getSession();
if(session==null || session.getAttribute(SessionConst.LOGIN_MEMBER)==null) {
log.info("미인증 사용자 요쳥");
response.sendRedirect("/member/login");
return false;
}
return true;
}
}
- 로그인 한 사용자가 아니면 "/member/login"(로그인 폼)으로 이동시킨다.
WebConfig
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/*","/member/login","/member/create","/member/saved/*","/css/**","/js/**");
}
}
- order(1): 우선순위 1로 설정
- addPathPatterns("/**"): 모든 경로를 포함한다.
- excludePathPatterns("/*", ...): 그 중 welcomePage, 로그인 폼, 회원가입 폼, 회원상세 폼, css, js의 경로는 제외한다.
인터셉터 등록 시 부트스트랩 적용 안 되는 이슈가 있었다. 여기를 클릭해 확인할 수 있다.
회원가입을 할 때 같은 loginId를 가지는 사용자를 생성하지 않기위해 이전에 MemberService에 validateDuplicateMember()를 만들어서 create()에서 검증했지만 뷰에서 검증처리 메시지를 구현하지 않았기에 중복된 ID로 가입을 하면 바로 WhiteLabel Error Page가 떴다. 검증처리 메시지가 나오도록 수정해보자.
MemerService
@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class MemberService {
private final MemberRepository memberRepository;
public Member createMember(Member member) {
if(!validateDuplicateMember(member)) {
memberRepository.save(member);
return member;
}
return null;
}
public boolean validateDuplicateMember(Member member) {
Member findMember = memberRepository.findByLoginId(member.getLoginId());
if(findMember!=null) {
return true;
}
return false;
}
...
}
- createMember()가 void에서 Member를 반환하도록 수정하였다.
- validateDuplicateMemer()도 void에서 boolean을 반환하도록 수정하였다.
- 이전엔 IllegalStateException 예외를 던졌다.
MemberController
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
private final LoginService loginService;
@GetMapping("/create")
public String createForm (@ModelAttribute Member member) {
return "member/createMemberForm";
}
@PostMapping("/create")
public String create (@Validated @ModelAttribute Member member, BindingResult bindingResult,
RedirectAttributes redirectAttributes) {
if(bindingResult.hasErrors()) {
return "member/createMemberForm";
}
Member newMember = memberService.createMember(member);
if(newMember==null) {//중복된 ID일 경우
bindingResult.reject("duplicateID","해당 아이디가 이미 존재합니다.");
return "member/createMemberForm";
}
redirectAttributes.addAttribute("memberId",member.getId());
return "redirect:/member/saved/{memberId}";
}
}
- memberService.create()하여 정상적으로 가입됐으면 정상흐름을 타고, 가입되지 않았다면 newMember가 null을 가지므로 bindingResult에 글로벌 오류를 추가하여 다시 회원가입 폼으로 보낸다.
- 필드오류와 글로벌 오류(객체 오류)는 다른 것이다.
- BindingResult 가 있으면 오류 정보( FieldError )를 BindingResult 에 담아서 컨트롤러를 정상 호출한다.
- 검증공부 다시 해야겠다. 확실히 모르는 것 같다.
- redirectAttributes.addAttribute()로 추가된 속성이 pathVariable에 포함되면 PathVariable에 바인딩해주고 나머지는 쿼리 파라미터(url 뒤에 붙음)로 처리
createMemberForm.html
<body class="text-center">
<main class="form-signin">
<form th:action th:object="${member}" method="post">
<h1 class="h3 mb-3 fw-normal">회원가입</h1>
<div th:if="${#fields.hasGlobalErrors()}">
<p class="field-error" th:each="err : ${#fields.globalErrors()}"
th:text="${err}">전체 오류 메시지</p>
</div>
...
- 만약 글로벌 오류가 있으면 출력하는 코드 추가

'토이 프로젝트 > 게시판 프로젝트' 카테고리의 다른 글
8. 게시판 프로젝트 - 로그아웃, 회원 정보 수정 (0) | 2022.08.11 |
---|---|
7. 게시판 프로젝트 - BaseTimeEntity, MemberDto (0) | 2022.08.11 |
5. 게시판 만들기 - 회원가입 필드 오류 검증, PRG 패턴 (0) | 2022.08.09 |
4. 스프링 게시판 만들기 - 로그인 기능1(세션) , 필드 오류 검증 (0) | 2022.08.09 |
3. 스프링 게시판 만들기 - 컨트롤러 생성(Member), 회원가입 기능, 뷰 생성 (0) | 2022.08.09 |