[SpringBoot] TIL 076 - 23.11.10

유진·2023년 11월 9일
0

SpringBoot : 로그인, 쿠키

MemberController.java

package edu.kh.project.member.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import edu.kh.project.member.model.dto.Member;
import edu.kh.project.member.model.service.MemberService;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

@Controller
@SessionAttributes({"loginMember"})
@RequestMapping("/member")
public class MemberController {
	
	@Autowired
	private MemberService service;
   
   @PostMapping("/login")
   public String login(Member inputMember, Model model,
                  @RequestHeader("referer") String referer,
                  RedirectAttributes ra,
                  @RequestParam(value="saveId", required = false) String saveId,
                  HttpServletResponse resp
                  ) {
      
      Member loginMember = service.login(inputMember);

      String path = "redirect:";
      
      if(loginMember != null) {    // 로그인 성공시
         path += "/"; 
         
         
         model.addAttribute("loginMember", loginMember);

         Cookie cookie = new Cookie("saveId", loginMember.getMemberEmail());
         
         if(saveId != null) { // 체크가 되었을 때
            
            cookie.setMaxAge(60*60*24*30);
            
            
         } else { // 체크가 안되었을 때 

            cookie.setMaxAge(0);
            
         }
         
         cookie.setPath("/");

         resp.addCookie(cookie);
         
         
      } else { // 로그인 실패
         path += referer;
         
         ra.addFlashAttribute("message", "아이디 또는 비밀번호 불일치");
      }
      
      return path;
   }
   
   @GetMapping("/logout")
   public String logout(SessionStatus status) {
      
      status.setComplete();
      return "redirect:/";      
      
   }
   

}

MemberService.java

package edu.kh.project.member.model.service;

import edu.kh.project.member.model.dto.Member;

public interface MemberService {

	/** 로그인 서비스
	 * @param inputMember (email, pw)
	 * @return email, pw가 일치하는 회원정보 또는 null
	 */
	Member login(Member inputMember);

	/** 회원 가입 서비스
	 * @param inputMember
	 * @return result
	 */
	int signUp(Member inputMember);
	
}

MemberServiceImpl.java

package edu.kh.project.member.model.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.kh.project.member.model.dao.MemberDAO;
import edu.kh.project.member.model.dto.Member;

@Service
public class MemberServiceImpl implements MemberService{
	
	@Autowired
	private MemberDAO dao;
	
	@Autowired // bean으로 등록된 객체 중 타입이 일치하는 객체를 DI(의존성 주입)
	private BCryptPasswordEncoder bcrypt;
	
	// 암호화가 필요한 곳? 로그인, 회원가입
	
	@Override
	public Member login(Member inputMember) {
		
		// dao 메서드 호출
		Member loginMember = dao.login(inputMember);
		
		if(loginMember != null) { // 아이디가 일치하는 회원이 조회된 경우
			
			if(bcrypt.matches(inputMember.getMemberPw(), loginMember.getMemberPw())) {
				
				// 비밀번호를 유지하지 않기 위해서 로그인 정보에서 제거
				loginMember.setMemberPw(null);
				
			} else { // 다를 경우
				loginMember = null;
			}
			
		} 
		
		return loginMember;
	}

	
	// 회원 가입 서비스
	@Transactional
	@Override
	public int signUp(Member inputMember) {
		
		// 비밀번호 암호화 (Bcrypt) 후 다시 inputMember 세팅
		String encPw = bcrypt.encode(inputMember.getMemberPw());
		inputMember.setMemberPw(encPw);
		
		return dao.signUp(inputMember);
	}

}

MemberDAO.java

package edu.kh.project.member.model.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import edu.kh.project.member.model.dto.Member;

@Repository
public class MemberDAO {
	
	@Autowired // 객체로 만들어진 것 -> 의존성 주입
	private MemberMapper memberMapper; // MemberMapper 인터페이스를 상속받은 자식 객체
										// 자식객체가 sqlSessionTemplate 이용
	
	
	public Member login(Member inputMember) {
		// return sqlSession.selectOne("memberMapper.login", inputMember);
		return memberMapper.login(inputMember);
	}


	public int signUp(Member inputMember) {
		return memberMapper.signUp(inputMember);
	}

}

MemberMapper.java

package edu.kh.project.member.model.dao;

import org.apache.ibatis.annotations.Mapper;

import edu.kh.project.member.model.dto.Member;

//마이바티스 mapper와 연결된 인터페이스임을 명시
//- 해당 인터페이스에 메서드명과 mapper.xml파일의 id가 일치하는 태그가 자동으로 연결됨
//-> 단, mapper.xml파일의 namespcae가 해당 인터페이스의 패키지명+클래스명으로 등록되어 있어야함.
//- @Mapper가 작성된 인터페이스를 사용하면 DAO에서 sqlSessionTemplate 객체를 사용하지 않아도됨
//-> DAO에 매퍼 인터페이스를 @Autowired 하면 sqlSessionTemplate 객체가 의존성 주입됨.
@Mapper
public interface MemberMapper {
	
	Member login(Member inputMember);
	// 메서드 이름 login -> 연결된 mapper.xml에서 id가 login인 sql이 수행

	int signUp(Member inputMember);
}

member-mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!-- namespace를 Mapper 인터페이스로 지정 -->
<mapper namespace="edu.kh.project.member.model.dao.MemberMapper"> <!-- MemberMapper와 mapper.xml을 연결(매핑)해주는 역할 -->
	
	<resultMap type="Member" id="member_rm">
		<id property="memberNo" column="MEMBER_NO" />
		<result property="memberEmail" column="MEMBER_EMAIL" />
		<result property="memberPw" column="MEMBER_PW" />
		<result property="memberNickname" column="MEMBER_NICKNAME" />
		<result property="memberTel" column="MEMBER_TEL" />
		<result property="memberAddress" column="MEMBER_ADDR" />
		<result property="profileImage" column="PROFILE_IMG" />
		<result property="enrollDate" column="ENROLL_DATE" />
		<result property="memberDeleteFlag" column="MEMBER_DEL_FL" />
		<result property="authority" column="AUTHORITY" />
	</resultMap>

	<!-- 로그인 -->
	<select id="login" resultMap="member_rm">
		SELECT MEMBER_NO, MEMBER_EMAIL, MEMBER_NICKNAME, MEMBER_PW,
		MEMBER_TEL, MEMBER_ADDR, PROFILE_IMG, AUTHORITY,
		TO_CHAR(ENROLL_DATE, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분" SS"초"') AS ENROLL_DATE
		FROM "MEMBER"
		WHERE MEMBER_DEL_FL = 'N'
		AND MEMBER_EMAIL = #{memberEmail}
	</select>
	
	<!-- 회원 가입 -->
	<insert id="signUp">
		INSERT INTO "MEMBER"
		VALUES(SEQ_MEMBER_NO.NEXTVAL
		, #{memberEmail}
		, #{memberPw}
		, '${memberNickname}'
		, #{memberTel}
		, #{memberAddress}
		, NULL, DEFAULT, DEFAULT, DEFAULT)
	</insert>
</mapper>

아이디 : user01@kh.or.kr
비밀번호 : pass01! 입력 후 로그인 버튼 클릭 시,


쿠키

타임리프 -> 쿠키를 바로 꺼내 쓸 수 없음
(자바스크립트가 필요!)

main.js

// 자바스크립트로 쿠키 얻어오기
function getCookie(key) {

    //saveId=user01@kh.or.kr; test=가나다; aaa=100
    const cookies = document.cookie; // 브라우저에 있는 전체쿠키 가져오기
                    // ['saveId=user01@kh.or.kr', 'test=가나다', 'aaa=100']
    const cookieList = cookies.split("; ").map(cookie => cookie.split("=")); // 배열 -> K:V 형태

    //배열.map() : 배열의 모든 요소를 순차접근하여 특정 함수 수행 후
    //              수행 결과를 이용해서 새로운 배열을 만드는 함수
    // ex) [1,2,3].map(num => num*2) -------> [2,4,6]

    // [ ['saveId', 'user01@kh.or.kr'], ['test, 가나다'], ['aaa=100'] ]
    console.log(cookieList);

    const obj = {};

    for(let i = 0; i < cookieList.length; i++) {
        obj[cookieList[i][0]] = cookieList[i][1];
    }

    return obj[key];
}

// 쿠키에 saveId가 있을 경우
if( document.querySelector("input[name='memberEmail']") != null ) {
    // 화면에 memberEmail 입력박스가 있을 경우

    const saveId = getCookie("saveId");

    // 있으면 이메일값, 없으면 undefined

    if(saveId != undefined) { // 쿠키에 저장된 이메일이 있을 때
        document.querySelector("input[name='memberEmail']").value = saveId;
        document.querySelector("input[name='saveId']").checked = true;
    }

}

0개의 댓글