스프링수업 22일차

하파타카·2022년 4월 25일
0

SpringBoot수업

목록 보기
22/23

한 일

유저 가입

  • DB 테이블 생성
  • Class, Mapper Interface
  • 컨트롤러와 뷰
  • 유효성 검사

로그인 (1)

  • class, Service
  • 컨트롤러와 뷰

유저 가입

DB 테이블 생성

user 테이블 생성

CREATE TABLE `mybatis`.`user` (
  `email` VARCHAR(100) NOT NULL,
  `password` VARCHAR(200) NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`email`)
);

Class, Mapper Interface


User클래스, UserMapper 인터페이스 생성

User클래스

- User -

@Data		// get set toString
@AllArgsConstructor		// 모든 필드변수로 생성자 생성
public class User {
	
	private String email;
	private String password;
	private String name;

}

Mapper인터페이스

- UserMapper -

@Mapper
public interface UserMapper {

	@Insert("INSERT INTO user VALUES(#{email}, #{password}, #{name})")
	public int insert(User user);
	
	@Update("UPDATE user SET password = #{password} WHERE email = #{eamil}")
	public int update(User user);
	
	@Delete("DELETE FROM user WHERE email = #{email}")
	public int delete(User user);
	
	@Select("SELECT count(*) FROM user")
	public int count();
	
	@Select("SELETE * FROM user")
	public List<User> selectAll();
	
	@Select("SELECT * FROM user WHERE email = #{email}")
	public User selectByEmail(String email);
}

board와 달리 login쪽은 매퍼 xml파일없이 현재 자바매퍼에서 쿼리처리를 모두 할 예정.

컨트롤러와 뷰

컨트롤러

- UserController -

@Controller
public class UserController {

	@Autowired
	private UserMapper userMapper;
	
	@GetMapping("/register")
	public Object getUsersView(@ModelAttribute User user) {
		// register의 user객체를 model로 전달
		return "register";
	}
}

- register.html -

<div class="card-header">
  <h4 class="font-weight-bolder">가입하기</h4>
  <p class="mb-0" th:text="${message} ?: '가입양식을 작성해주세요'"></p>
</div>
<div class="card-body bg-white">
  <form role="form" th:action="@{/register}" method="post" th:object="${user}">
    <div class="input-group input-group-outline mb-3">
      <label class="form-label">Name</label>
      <input type="text" class="form-control" th:field="*{name}" required />
    </div>
    <div class="input-group input-group-outline mb-3">
      <label class="form-label">Email</label>
      <input type="email" class="form-control" th:field="*{email}" required />
    </div>
    <div class="input-group input-group-outline mb-3">
      <label class="form-label">Password</label>
      <input type="password" class="form-control" th:field="*{password}" required />
    </div>
    <div class="form-check form-check-info text-start ps-0">
      <input class="form-check-input" type="checkbox" value="" id="flexCheckDefault" checked />
      <label class="form-check-label" for="flexCheckDefault"> I agree the <a href="javascript:;" class="text-dark font-weight-bolder">Terms and Conditions</a> </label>
    </div>
    <div class="text-center">
      <button type="submit" class="btn btn-lg bg-gradient-primary btn-lg w-100 mt-4 mb-0">가입하기</button>
    </div>
  </form>
</div>
<div class="card-footer bg-white text-center pt-0 px-lg-2 px-1">
  <p class="mb-2 text-sm mx-auto">
    이미 계정이 있습니까?
    <a th:href="@{/pages/login.html}" class="text-primary text-gradient font-weight-bold">로그인</a>
  </p>
</div>
</div>

th:text="${message} ?: '가입양식을 작성해주세요'": message가 없으면 '가입양식을 작성해주세요' 문구가 나타남.
th:object="${user}" model객체를 통해 user의 정보를 받아 form내의 각 field에 데이터를 할당.
required로 반드시 입력을 해야 넘어갈 수 있도록 해줌.

유효성 검사

- UserController -

@PostMapping("/register")
public String postUser(User user, Model model, HttpSession session, RedirectAttributes attr) {
	// 클라이언트 단 또는 서버 단에서 데이터 유효성 체크를 적용하는 것을 권장

	User duplicatedUser = userMapper.selectByEmail(user.getEmail());	// 이메일이 같은 유저가 없으면 null
	if (duplicatedUser == null) {
		// 이메일 중복이 아니므로 가입처리
		userMapper.insert(user);
		attr.addFlashAttribute("message", "가입되었습니다.");
		return "redirect:/login";
	} else {
		// 이메일 중복이므로 메시지와 함께 리다이렉트로 돌아감
		attr.addFlashAttribute("message", "email 중복입니다.");
		return "redirect:/register";
	}		
}

- register.html -

<style>
  input:invalid:focus {
    /* input태그의 조건이 충족되지 않았을때 */
    background-image: linear-gradient(rgb(172, 255, 193), lightblue) !important;
  }
</style>
<input type="text" class="form-control" th:field="*{name}" minlength="2" maxlength="5" required />
<input type="email" class="form-control" th:field="*{email}" required />
<input type="password" class="form-control" th:field="*{password}" minlength="4" maxlength="10" required />

간단한 유효성검사이므로 클라이언트에서 진행.

input:invalid:focus는 입력한 값이 input태그의 조건에 맞지 않을 경우 실행. 여기서는 background컬러가 들어감.
!important속성을 사용해 부트스트랩보다 우선순위를 높게 적용
minlength="?": 최소 글자수를 지정
maxlength="?": 최대 글자수를 지정

테스트



가입하기에 성공했을 때.


email이 중복일때는 message가 나타난 로그인 화면으로 돌아간다.


로그인 (1)

class, Service

- Login -

@Data
@AllArgsConstructor
public class Login {
	private String email;
	private String password;
	private String error;	// 오류메시지를 저장하는 문자열
}

- LoginService -

@Service
public class LoginService {

	@Autowired
	private UserMapper userMapper;
	
	// 인증하기 메서드 : 실패할 경우 login 객체에 error메시지 입력
	public void authenticate(Login login) {
		// 이메일 검색으로 유저찾기
		User user = userMapper.selectByEmail(login.getEmail());
		
		if (user == null) {
			login.setError("이메일이 존재하지 않습니다.");
		} else {
			if (!user.getPassword().equals(login.getPassword())) {
				login.setError("패스워드가 틀립니다.");
			} else {
				login.setError(null);	// 에러없음(이메일 인증됨)
			}
		}
	}

	// 유저 찾기 메서드 : 이메일로 유저 찾기
	public User findUserByEmail(String email) {
		User user = userMapper.selectByEmail(email);
		return user;
	}
}

UserMapper를 이용

컨트롤러와 뷰

컨트롤러

- LoginController -

@Controller
public class LoginController {
	
	@Autowired
	private LoginService loginService;
	
	@GetMapping("/login")
	public String getLoginView(@ModelAttribute Login login) {
		// 로그인페이지에 Login객체 login을 바인딩
		return "login";
	}

	/**
	 * 로그인 처리 (인증되었을 경우 user객체를 세션에 저장)
	 * @param login
	 * @param model
	 * @param session
	 * @return
	 */
	@PostMapping("/login")
	public String postLogin(Login login, Model model, HttpSession session) {
		loginService.authenticate(login);	// 인증 메서드 실행(실패시 에러메시지 입력됨)
		
		if (login.getError() != null) {
			model.addAttribute("message", login.getError());
			return "login";		// 로그인 실패
		} else {
			User user = loginService.findUserByEmail(login.getEmail());
			session.setAttribute("user", user);		// 세션에 인증된 유저를 저장
			System.out.println(user.toString());	// 유저 출력
			return "redirect:/board/list";
		}
	}

	@GetMapping("/logout")
	public String getLogout(HttpSession session) {
		session.removeAttribute("user");
        //session.remove ? ("user");
		return "redirect:/login";
	}
}

- login.html -

<style>
  input:invalid:focus {
    /* input태그의 조건이 충족되지 않았을때 */
    background-image: linear-gradient(rgb(172, 255, 193), lightblue) !important;
  }
</style>

<div class="card-body">
  <p class="text-primary" th:if="${message}" th:text="${message}"></p>
  <form role="form" class="text-start" th:action="@{/login}" method="post" th:object="${login}">
    <div class="input-group input-group-outline my-3">
      <label class="form-label">Email</label>
      <input type="email" class="form-control" th:field="*{email}" required />
    </div>
    <div class="input-group input-group-outline mb-3">
      <label class="form-label">Password</label>
      <input type="password" class="form-control" th:field="*{password}" minlength="4" maxlength="10" required />
    </div>
    <div class="form-check form-switch d-flex align-items-center mb-3">
      <input class="form-check-input" type="checkbox" id="rememberMe" />
      <label class="form-check-label mb-0 ms-2" for="rememberMe">Remember me</label>
    </div>
    <div class="text-center">
      <button type="submit" class="btn bg-gradient-primary w-100 my-4 mb-2">로그인</button>
    </div>
    <p class="mt-4 text-sm text-center">
      계정이 없습니까?
      <a th:href="@{/register}" class="text-primary text-gradient font-weight-bold">가입하기</a>
    </p>
  </form>
</div>

테스트

http://localhost:8080/login 에서 앞서 가입한 eamil로 로그인


로그인에 성공하면 게시글리스트페이지로 이동한다.


로그인 실패시 message가 출력되며 로그인 페이지로 돌아간다.

profile
천 리 길도 가나다라부터

0개의 댓글

관련 채용 정보