[BE]User Layer

김주언·2022년 6월 15일
0

TODO LIST

목록 보기
9/18
post-thumbnail

User Layer

REST Security 구현을 위해 클래스를 작성하고 스프링 시큐리티를 이용해 인증과 인가를 구현한다.

사용자 관리를 위해 사용자와 관련된 모델, 서비스, repository, 컨트롤러가 필요하다.
TODO 레이어 구성했던 것 처럼, TODO 말고 USER를 저장하면 됨

  • UserEntity
  • UserRepository
  • UserService
  • UserDTO / UserController

스프링 시큐리티 사용하지 않아도 사용자 기능 구현에 필요한 클래스들이라서 독립적인 사용이 가능하다.
그래도 쓸거임 스프링 시큐리티 🥴


UserEntity.java

package com.example.demo.model;
// import 생략

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = "email")})
public class UserEntity {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;

    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String email;

}
  • @Data : 클래스 멤버 변수의 Getter / Setter 구현
  • @Entity : 자바클래스를 엔티티로 구현
  • @Builder : 빌더 디자인 패턴 제공
  • @NoArgsConstructor : 매개변수 없는 생성자 구현
  • @AllArgsConstructor : 클래스의 모든 멤버변수를 매개변수로 받는 생성자 구현

자바 클래스를 엔티티로 정의할 때 주의점
1. 클래스에 매개변수가 없는 생성자가 필요
2. Getter / Setter 필요
3. 기본 키 설정 해줘야함

  • @Id : 정의된 필드를 기본키로 설정
  • @GeneratedValue : 자동으로 기본키 생성
  • @GenericGenerator : 기본키 생성 방법 지정



UserRepository.java

함수 작성 시 메소드 이름 명명 규칙 따라야함 (JPA 사용하니까)

package com.example.demo.persistence;
// import ...
@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
    UserEntity findByEmail(String email);

    Boolean existsByEmail(String email);

    UserEntity findByEmailAndPassword(String email, String password);
    
}




UserService.java

package com.example.demo.services;

// import ...

@Slf4j
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public UserEntity create(final UserEntity userEntity) {
        if (userEntity == null || userEntity.getEmail() == null)  {
            throw new RuntimeException("Invalid args");
                    
        }
        final String email = userEntity.getEmail();
        if (userRepository.existsByEmail(email)) {
            log.warn("{} already exists",email);
            throw new RuntimeException("Email already exists");
        }
        return userRepository.save(userEntity);
    }

    public UserEntity getByCredentials(final String email, final String password) {
        return userRepository.findByEmailAndPassword(email, password);
    }
    
}
  • create : UserRepository를 사용하여 사용자를 생성한다.
  • getByCredentials : 이메일과 패스워드를 이용하여 로그인 시 인증에 사용한다.




UserDTO.java

package com.example.demo.dto;

//import ...

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
    private String token;
    private String email;
    private String id;
    private String username;
    private String password;
}

UserController.java

현재 사용자 가져오기/ 회원가입 기능 구현

package com.example.demo.controller;

// import ...

@Slf4j
@RestController
@RequestMapping("/auth")
public class UserController {
    @Autowired
    private UserService userService;
}
  • @RestController : REST API 사용
  • @RequestMapping("/auth") : 경로 지정
  • UserService 기능 사용

클래스 메서드 구현

회원가입 - registerUser()

@PostMapping("/signup")
public ResponseEntity<?> registerUser(@RequestBody UserDTO userDTO) {
        try {
        
        // 요청으로 받은 사용자 정보 (userDTO) 사용하여 엔티티 생성
            UserEntity user = UserEntity.builder()
                    .username(userDTO.getUsername())
                    .email(userDTO.getEmail())
                    .password(userDTO.getPassword())
                    .build();
		
        // 서비스 사용하여 생성한 사용자를 레포지터리에 저장한다
            UserEntity registeredUser = userService.create(user);
        
        // 응답으로 보낼 DTO 생성
            UserDTO responseUserDTO = UserDTO.builder()
                    .id(registeredUser.getId())
                    .email(registeredUser.getEmail())
                    .username(registeredUser.getUsername())
                    .build();

            return ResponseEntity.ok().body(responseUserDTO);
        } catch (Exception e) {
        // 사용자 정보는 항상 하나 -> 리스트x
            ResponseDTO responseDTO = ResponseDTO.builder().error(e.getMessage()).build();
            return ResponseEntity.badRequest().body(responseDTO);
        }

    }
  • @PostMapping("/signup") : HTTP POST 메서드 설정

로그인 - authenticate()

@PostMapping("/signin")
public ResponseEntity<?> authenticate(@RequestBody UserDTO userDTO) {
        UserEntity user = userService.getByCredentials(
                userDTO.getEmail(), userDTO.getPassword());
        if (user != null) {
            final UserDTO responseUserDTO = UserDTO.builder()
                    .email(user.getEmail())
                    .id(userDTO.getId())
                    .build();
            return ResponseEntity.ok().body(responseUserDTO);
        } else {
            ResponseDTO responseDTO = ResponseDTO.builder()
                    .error("Fail to Login").build();
            return ResponseEntity
                    .badRequest()
                    .body(responseDTO);
        }
    }

그냥 로그인...

signup 테스트 화면 ↓

signin 테스트 화면 ↓


현재 시점에서의 문제점

  1. 로그인 상태 유지가 안됨
  2. 사용자의 로그인 여부 확인 하지도 않음 ㅋㅋ
  3. 패스워드 암호화 안해줫음

으아아~

profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글