main.html
<form action="/member/login" method="POST" id="loginForm">
<fieldset class="id-pw-area">
<!-- 아이디/비밀번호 입력 -->
<section>
<input type="text"
name="memberEmail"
placeholder="이메일">
<input type="password"
name="memberPw"
placeholder="비밀번호">
</section>
<!-- 로그인 버튼 -->
<section>
<button>로그인</button>
</section>
</fieldset>
<label>
<!-- label 태그 : input 태그의 제목을 나타내는 태그 -->
<input type="checkbox" name="saveId">
아이디 저장
</label>
<article class="signup-find-area">
<a href="/member/signup">회원가입</a>
<span> | </span>
<a href="#">ID/PW 찾기</a>
</article>
</form>

catalog Mapper 로 해서 만들어야함 Config 파일과 다름
Controller
@Controller
@Slf4j
@RequestMapping("member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService service;
}
ServiceImpl
@Service
@Transactional(rollbackFor=Exception.class)
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberMapper mapper;
}
모든 예외 발생 시 rollback ( 기본 RuntimeException )
MemberMapper interface
@Mapper
public interface MemberMapper {
}
member-mapper.xml
만들자마자 cache-ref 지워야함
<?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" >
<mapper namespace="com.home.board.member.model.mapper.MemberMapper">
</mapper>
namespace 에 연결할 Mapper 인터페이스 패키지명+인터페이스명 작성하면 Mapper interface method 호출 시 xml 파일에 작성된 태그 중 메서드명과 일치하는 id 를 가진 SQL 이 수행됨
MemberController
@PostMapping("login")
public String login(Member inputMember,
RedirectAttributes ra,
Model model) {
// 로그인 서비스 호출
Member loginMember = service.login(inputMember);
return "redirect:/"; // 메인페이지 재요청
}
inputMember : 커맨드 객체(@ModelAttribute 생략)
(memberEmail, memberPw 세팅된 상태)
html 에서 form 태그 안에 input 태그 name 속성으로 memberEmail, memberPw 값 받아서 그대로 넘겨줌
ServiceImpl
입력된 문자열(비밀번호)에 salt 를 추가한 후 암호화하는 애
(똑같은 평문을 암호화해도 다 다른 결과값이 나옴)
비밀번호 확인 방법
-> BCryptPasswordEncoder.matches(평문 비밀번호, 암호화된 비밀번호)
-> 평문 비밀번호와 암호화된 비밀번호가 같은 경우 true 아니면 false 반환
로그인 / 비밀번호 변경 / 탈퇴 등 비밀번호가 입력되는 경우
DB에 저장된 암호화된 비밀번호를 조회해서 matches() 메서드로 비교해야 함.
sha 방식 암호화(BCrypt 이전 사용 방식)는 똑같은 평문을 암호화하면 똑같은 결과값이 나옴
SecurityConfig 클래스
@Configuration : 설정용 객체임을 명시 + 객체로 생성해서 내부 코드를 서버 실행시 모두 수행
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
@Bean : 개발자가 수동으로 생성한 객체의 관리를 스프링에게 넘기는 어노테이션 (Bean 등록)
MemberSerivceImpl
private final BCryptPasswordEncoder bcrypt;
ServiceImpl
String bcryptPassword = bcrypt.encode(inputMember.getMemberPw());
log.debug("bcryptPassword : " + bcryptPassword);
DBeaver
UPDATE "MEMBER" SET
MEMBER_PW = '암호화된 비밀번호'
WHERE MEMBER_NO = 1;
DB에 평문상태로 비밀번호 저장해두면 안됨
ServiceImpl
Member loginMember = mapper.login(inputMember.getMemberEmail());
member-mapper.xml
parameterType 속성은 필수 속성 아님
TypeHandler 를 이용해서 자료형을 판별할 수 있음
<select id="login" parameterType="string" resultType="Member">
SELECT MEMBER_NO, MEMBER_EMAIL, MEMBER_NICKNAME, MEMBER_PW,
MEMBER_TEL, MEMBER_ADDRESS, PROFILE_IMG, AUTHORITY,
TO_CHAR(ENROLL_DATE, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분" SS"초"') ENROLL_DATE
FROM "MEMBER"
WHERE MEMBER_EMAIL = #{memberEmail}
AND MEMBER_DEL_FL = 'N'
</select>
비밀번호까지 돌려주는 이유는 Service 에서 평문으로 들어온 비밀번호와 sql 에 저장된 암호화된 비밀번호를 조회해야해서
if(loginMember == null) return null;
loginMember 조회 결과가 있을 때
2-1. 비밀번호가 일치하지 않으면 return null;
.matches(평문,암호화)
부정논리연산자 붙여서 일치하지 않을 때 true 값 나오게
if(!bcrypt.matches(inputMember.getMemberPw(), loginMember.getMemberPw())) {
return null;
}
2-2. 비밀번호가 일치할 때 로그인 시켜줘야함
(단, 로그인 결과에서 가지고 온 비밀번호는 제거시켜줘야함)
(loginMember 는 session scope 에 실어둘 거라서)
return
loginMember.setMemberPw(null);
return loginMember;
MemberController
로그인 실패 시
if(loginMember == null) {
ra.addFlashAttribute("message", "아이디 또는 비밀번호가 일치하지 않습니다.");
}
로그인 성공 시
if(loginMember != null) {
// loginMember 를 session scope 에 올려둘 거임
model.addAttribute("loginMember", loginMember);
// request scope 에 올려둔 거
}
Model 을 session scope 에 올리는 방법
Controller 클래스 상단에 @SessionAttributes({"loginMember"}) 어노테이션 추가
-> Model 에 추가된 속성 중 key 값이 일치하는 속성을 session scope 로 변경해주겠다는 어노테이션
@SessionAttributes ({"key", "key", ...}) 쭉 나열해서 사용 가능