웹 개발 Spring Day10 세션 / 쿠키 @SessionAttribute

김지원·2022년 8월 18일
0

WebDevelop2

목록 보기
30/34

UserService : putUser -> Register 로 변경
-> 코드를 간결하게 줄이자 Controller말고 Service에 로직을 구현하자.

-> UserService Register

if (this.userMapper.selectByUserCountByEmail(user.getEmail()) > 0) {
    return RegisterResult.FAILURE_DUPLICATE_EMAIL;
} // 이메일 중복 
Date currentDate = new Date();
user.setPassword(CryptoUtils.hash(CryptoUtils.Hash.SHA_512, user.getPassword()));
user.setCreatedAt(currentDate);
if (this.userMapper.insertUser(user) == 0) {
    return CommonResult.FAILURE;
}

-> UserController postRegister

  • 서비스에서 로직을 구현하니 훨씬 짧아졌다.

UserService : getUserByEmailAndPassword -> login 으로 변경
-> UserService login

public Enum<? extends IResult> login(UserEntity user) { // 이 user 은 이메일과 비밀번호만 가지고 있다.
    user.setPassword(CryptoUtils.hash(CryptoUtils.Hash.SHA_512, user.getPassword()));
    UserEntity signedUser = this.userMapper.selectUserByEmailAndPassword(user.getEmail(), user.getPassword());
    if (signedUser == null) { // 유저의 이메일 혹은 비밀번호가 틀렸다.
        return CommonResult.FAILURE;
    }
    if (!signedUser.isEmailVerified()) {
        return LoginResult.FAILURE_EMAIL_NOT_VERIFIED;
    }
    user.setEmail(signedUser.getEmail())
            .setPassword(signedUser.getPassword())
            .setName(signedUser.getName()) // 로그인이 성공하면 추가로 값을 가져온다. singedUser 을 통해서
            .setCreatedAt(signedUser.getCreatedAt())
            .setEmailVerified(signedUser.isEmailVerified());
    return CommonResult.SUCCESS;
}

현재까지는 로그인이 되는지만 확인을 하지 로그인을 했다는 기억을 하지 않는다.
로그인을 했다는 기록을 남기자.

이전에는 setAttribute를 request에 다이렉트넣는 방법과 ModelAndView의 addObject 하는 방법을 사용했었다.
세션을 가지고와서 setAttribute를 해보자.

-> UserEntity 정적 상수 추가

-> UserController postLogin

세션 / 쿠키

  • Session을 사용해서 로그인을 하게 되면 JSESSIONID 라는 이름으로 이상한 값을 가지는 쿠키가 하나 생기게 된다.
A9D6D04DA11DF6E93D5B4911DD8D8BF3

이 쿠키값이 현재 내가 사용하는 브라우저의 사용자를 인식할 수 있는 열쇠같은 것이다. (key)

실제 세션의 형태 / Session 이 만들어지는 과정

HashMap<String, HashMap<String, Object>> sessionStroage = ?;
 -- HashMap안에 HashMap이 존재하는 형태로 존재
HashMap<String, Object> sessionValue = ?;
sessionValue.put("user", user);
sessionStroage.put("A9D6D04DA11DF6E93D5B4911DD8D8BF3", sessionValue);
 -- sessionStroage에 쿠키값을 추가하면 이 사용자에 대한 sessionStroage에 접근이 가능해진다.
A9D6D04DA11DF6E93D5B4911DD8D8BF3.get("user") 
 -- get하면 UserEntity타입의 user가 나온다.
서버를 다시 돌리기 전까지는 세션이 살아있고, 즉 로그인 상태가 유지가 되는 것.
A9D6D04DA11DF6E93D5B4911DD8D8BF3.put("user", null) -> UserEntity user
                                               ↑
                                  만약 로그아웃 한다면 null이 된다.
 -- 서버를 다시 돌리기 전까지는 세션이 살아있고, 즉 로그인 상태가 유지가 된다.
A9D6D04DA11DF6E93D5B4911DD8D8BF4.put("user", null) 
 -- 만일 JSESSIONID 가 달라지면 null(로그인 안한사람)이 나온다.

@SessionAttribute {Variable}

value    : HttpSession 객체에서 받아올 값의 키(이름)다.
required : 해당 키를 가지는 쌍이 없을 때 해당 속성 값이 true 이면 오류가 발생하고, false 이면 null을 사용한다.
  • HttpSession에 존재하는 값을 키로 가지고 올때 사용한다.

-> HomeController postLogin

  • @SessionAttribute 사용 : requires=false 꼭 명시를 해줘야하며 value 값은 상수만 가능하다.
    UserEntity.ATTRIBUTE_NAME 와 같은 정적인 상수없이 "user"로 하게 되면 다른 개발자들과 혼동이 올 수 있다. ( 다른 개발자가 User로 쓴다거나 UserEntity 를 사용했을 경우 처럼..)
  • required = true 라면 반드시 해당 이름으로 UserEntity타입의 객체가 세션에 들어있어야함을 의미한다.

로그인을 성공했을때만 추가해줘야하니깐 if문으로 걸어준다.
-> UserController postLogin


index.html → index.insigned.html 로 이름 변경

-> index.signed.html

-> HomeController getIndex

  • 로그인을 하게 되면 /home/index.signed 로 이동한다.

다음으로는 아래의 페이지 구현을 할 것임으로 유저의 프로필을 만들자.

-> profiles 테이블 생성

-> ProfileEntity + getter / setter + build메서드

  • equals hashCode email 과 name 설정 후 오버라이드

Controller에세 프로필을 선택한적 있으면 뷰페이지를 signed로 가고 없다면 profile로 가도록 설정한다.

if(user == null) {
    modelAndView.setViewName("home/index.unsigned");
} else if (profile == null) {
    modelAndView.setViewName("home/index.profile");
} else {
    modelAndView.setViewName("home/index.signed");
}
  • 현재 로그인을 하면 프로필 설정을 한 적이 없으니 home/index.profile 로 연결이 된다.
@SessionAttribute(value = ProfileEntity.ATTRIBUTE_NAME, required = false) ProfileEntity profile

프로필을 어떻게 작성했느냐에 대한 정보는 session에 집어넣는다.


그렇다면 회원가입과 동시에 프로필(계정)이 하나 생겨야한다.

-> UserService register

ProfileEntity profile = ProfileEntity.build()
        .setUserEmail(user.getEmail())
        .setName(user.getName())
        .setCreatedAt(currentDate)
        .setLastAccessAt(currentDate)
        .setProfileIndex((int) (Math.random() * 12 + 1)); // 프로필 사진을 몇번을 사용할 것인지에 대한 것

  • 총 12개의 프로필 사진을 Math.random 메서드를 이용하여 랜덤하게 인덱스를 주자.

-> IUserMapper insertProfile

int insertProfile(ProfileEntity profile);

-> UserService register

-> UserMapper insertProfile

  • 회원가입을 하면 profiles 테이블에 profile_index가 부여되며 레코드가 추가되면 된다.

그런데 profile에 관한 Controller를 따로 만들어서 관리하는게 좋을 것 같음으로 수정한다.
home/profile.html -> profile/choose.html 로 변경

-> ProfileController

-> HomeController

  • html 파일이 바뀌는 것이 아닌 redirect: : 주소자체가 바꿔지게 된다.

-> ProfileController

if (user == null) {
     modelAndView.setViewName("redirect:/user/login");
}
  • 로그인하지 않으면 로그인페이지로 이동

-> AddResult

-> ProfileService

-> IProfileMapper

insertProfile
selectProfilesByEmail
selectProfileCountByEmailAndName

-> ProfileService addProfile getProfiles

-> ProfileMapper.xml

profile
Software Developer : -)

0개의 댓글