logoStephen's 기술블로그

포스트 검색

제목, 태그로 포스트를 검색해보세요

#블로그만들기_04 #로그인 구현

#블로그만들기_04 #로그인 구현
SpringWebApp
성훈 김
2024년 2월 5일
목차

1️⃣ 프론트 먼저 확인 ( Html확인 )

💡
🔹프론트에서 정보를 넘겨줄 수 있는 구조가 되어있는지 먼저 확인해야된다. 🔹method 자리에 공백이 되면 기본 디폴트 값은 get 🔹enctype 자리에 공백이 되면 기본 디폴트 값은 xform데이터 🔹 name 속성 있는지 확인하고 받을 값의 이름이 일치하는지 확인
notion image
 

🔷 @ Form 태그와 Input태그 개념

notion image
notion image
 
 

2️⃣ 클라이언트 정보 받기 - DTO안 쓸때

🔷 방법 1

💡
⭐ 왜 post를 사용하나?? ➖get요청으로 정보를 전달하면, 이는 URL로 노출이 되게된다. ➖ 그래서 민감한 정보는 바디데이터로 보내야된다. 그래서 post요청 🔹 매개변수에 파라메터로 사용해서 정보를 받을 수 있다. 하지만 위험!!
notion image
 

🔷 방법 2

💡
🔹 그림 다시 그려서 정리하자 🔹 톰캣의 HttpServletRequest 클래스를 사용하여서 정보를 받아온다. 🔹 request.getParameter 에 키값을 사용해서 가져온다.
notion image
notion image
 

3️⃣ DTO 만들기 - 우린 DTO 사용한다.

💡
⭐ DTO(Data Transfer Object, 데이터 전송 객체)란 프로세스 간에 데이터를 전달하는 객체를 의미합니다. 🔹 사용자를 입력한 정보를 객체에 담아서 사용한다. 🔹 클라이언트가 서버측으로 전송하는 데이터 🔹 DB에서 Entity로 받고, Entity에서 DTO필요한 정보를 추려내서 브라우저에 전달
notion image
Java
package shop.mtcoding.blog.user;
import lombok.Data;

public class UserRequest {

    @Data // Getter, Setter, toString 자동 생성
    public class LoginDTO { //login정보로 사용할 DTO객
        private String username;
        private String password;
    }
}
 

🔷 값 받기 테스트

💡
🔹 login액션이 들어오면 해당 메소드 실행 🔹 return에서 리다이렉트를 않고 연결하면 로그인 정보를 얻자마자 버리는 셈 🔹 로그인 정보를 가지고 이동할려면 반드시 redirect: 사용!!! 🔹 로그인을 위해서는 session.setAttribute가 필요하기 떄문에 의존성 주입!!
Java
@RequiredArgsConstructor  //의존성 주입용 생성자생성
@Controller // IoC 컨테이너에 등록
public class UserController {
    private final UserRepository userRepository;
		private final HttpSession session;  // 세션을 DI해서 로그인 사용자 세션 부여시 사용

		@PostMapping ("/login") // html에서 'login'액션이 들어오면 해당 메소드 실행
		    public String login (UserRequest.LoginDTO requestDTO){
		        System.out.println(requestDTO); // 값이 잘 넘어오는지 테스
		
		        return "redirect:/"; // 여기서 리다이렉트를 하지 않으면
		    }                        // 로그인 정보를 버리고 새로 요청하게됨
}                                // 정보를 가지고 이동할려면 리다이렉트로 메인페이지 연결
notion image
 
 

4️⃣ 컨트롤러에 책임 부여하기

🔹 login메소드 전체 코드

Java
@PostMapping("/login")
public String login(UserRequest.LoginDTO requestDTO){

		// 1번 유효성 검사 - 아이디 길이가 3자 이하일 때
    if(requestDTO.getUsername().length() < 3){
        return "error/400"; // ViewResolver 설정이 되어 있음. (앞 경로, 뒤 경로 자동설정)
    }

    User user = userRepository.findByUsernameAndPassword(requestDTO);
		
		// 2번 유효성 검사 - 아이디 비밀번호가 틀려서 조회가 안될 때
    if(user == null){ 
				// 조회 안됨 (401)
        return "error/401";
    }else{ 
				// 조회 됐음 (인증됨)
				// HttpSession을 의존성 주입을 받아서 사용 - 락카에 담음 (StateFul)
				// HttpSession이란 해쉬맵에 키값 'sessionUser'에 밸류값을 'user'
        session.setAttribute("sessionUser", user); 
    }

    return "redirect:/"; // 컨트롤러가 존재하면 무조건 redirect 외우기
}
💡
⭐ 의존성 주입 🔹 @RequriedArgConstructor 사용하여 final선언된 HttpSession을 가져다 쓸 수 있다.
notion image
 
 

🔷 1번 유효성 검사 - 아이디 길이가 3자 이하일 때

💡
🔹 400번 에러페이지 만들기 → 프론트 작업 또는 View만들기 🔹 400번 응답코드는 클라이언트 쪽의 잘못된 요청
Java
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>클라이언트가 요청을 잘못함 400</h1>
</body>
</html>
 
💡
🔹 username에 의도적으로 두 글자만 넣어서 에러페이지 테스트
Java
// UserController의 login메소드
// get요청이지만 보안상의 이유로 post요청
@PostMapping ("/login") 
    public String login (UserRequest.LoginDTO requestDTO){
        // 유효성 검사 - 사용자id가 3자 이하인경우 400번 에러메시지 전달
        if(requestDTO.getUsername().length() < 3){
            return "error/400";
        }

        return "redirect:/";
    }
notion image
 
💡
🔹 정상작동 확인
notion image
 
 

🔷 401 에러페이지 만들기

💡
🔹 401에러 페이지는 인증에 실패 하였을 때 보여주는 페이지이다. 🔹 그냥 400번 페이지를 복사 붙여넣기 하여 이름만 바꿔준다.
notion image
 
💡
🔹 400번 페이지랑 내용은 거의 비슷하지만 메시지만 바꾸면된다. 🔹 메시지 → 인증에 실패하였습니다. 401
HTML
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<h1>인증에 실패하였습니다. 401</h1>

</body>
</html>
 
 

4️⃣ 모델 연결 (DB 요청)

 

🔷 모델 위임(UserRepository 담당) 할 메소드 만들기

💡
🔹 유효성을 통과하였다면 아래 코드를 만들어서 UserController >> login 메소드 내부에 구현한다. 🔹 메소드가 길더라도 메소드 자체에서 의미를 바로 파악할 수 있게끔 만드는 것이 포인트!! 🔹 아마 빨간색일텐데, 이는 아직 해당메소드 로직을 구현하지 않았기 때문 🔹 alt+enter으로 들어가면 자동으로 필요한 매개변수와 함께 만들어준다.
Java
// login메소드 내부에 유효성 검사 통과 후 구현
userRepository.findByUsernameAndPassword(requestDTO);
 
💡
결과 - 자동으로 틀을 만들어 준다. 이 내부에 로직을 구현한다.
notion image
 
 

🔷 쿼리 작성

💡
🔹 자바에 쿼리를 먼저 실행해보기 전에 데이터베이스에서 쿼리가 실제 작동하는지 쿼리문 테스트를 먼저 실행한다.
Java
// 테스트 쿼리문
// 먼저 데이터를 넣고 조회가 되는지 테스트
// 문자열에 쌍따옴표가 아니라 홑따옴표 기억하자
select * from user_tb where username='ssar' and password='1234'
 
 
💡
🔹 테스트 확인. DB에서 직접 테스트 할려면 문자열은 ''로 감싸야된다. 🔹 H2 콘솔로 로그인하여서, insert into 후에 테스트를 해봐야된다.
notion image
 
 

🔷 메소드 구현

💡
⭐ ORM은 데이터베이스 테이블을 객체 (클래스)로 변환해주는 역할, JPA (Java Persistence API)와 같은 ORM 프레임워크를 사용하여 데이터베이스 테이블을 Java 클래스로 매핑 🔹 두개의 값을 받으므로 객체로 담아야 된다. User 클래스 사용 🔹 em변수로 EntityManager를 사용중이므로, 결과값을 받아서 바로 User클래스에 매핑해 주는 문법이 User.class 사용이다. 🔹 User.class 를 적을 수 있는 이유는 User 엔티티가 구현되어 있어야 한다. 이렇게 되면 자동으로 User클래스에 Table 데이터를 파싱해서 담아준다.
Java
public void findByUsernameAndPassword(UserRequest.LoginDTO requestDTO) {
				//em변수로 EnityManager를 사용중이므로, 결과값을 받아서 바로 User클래스에 매핑해 주는 문법이 User.class 사용이다.
        Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class);
				// ?를 변수화 하여서 setParmeter로 값을 지정한다. '1'이 첫 번째 매개변수라면 1번째 물음표에 대입하라라는 뜻
        query.setParameter(1, requestDTO.getUsername());
        query.setParameter(2, requestDTO.getPassword());
        // 하나의 결과값만 기대하기 때문에 getSinglerResult 사용
        User user = (User) query.getSingleResult(); 
        return user;
    }
💡
이렇게 User클래스에 @Enitity 선언이 되어있어야지 EntityManager를 통해 User.class를 사용 할 수 있다.
notion image
 
 

5️⃣ 로그인 테스트 확인

💡
🔹 잘 작동하는지 확인 🔹 로그인 성공후 서버로 부터 set-cookie값을 받았다
notion image
 
 
💡
개발자도구>> Application>> Cookies로 들어가보면 jsessionid를 확인할 수 있다.
notion image