본문 바로가기
Project

[stock] 회원관리 - 회원가입

by sangyunpark 2023. 9. 21.

회원가입에 필요한 라이브러리를 build.gradle에 추가하자

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation group: 'io.jsonwebtoken', name:'jjwt', version:'0.9.1'

 

권한 정보를 enum으로 만들어준다!

package com.example.stock.model.constants;

public enum Authority {
    ROLE_READ,
    ROLE_WRITE;
}

 

회원에 대한 Entity를 만들어주자

 

package com.example.stock.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class MemberEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    
}

 

Entity를 만들면서 문득 드는 생각

왜? id는 Long type으로 만들어주는 것일까?

https://joyful-class-maker.tistory.com/119

 

[JPA] Entity 설계시 ID 값을 Long으로 지정하는 이유

JPA 공부중 의문이 생겼다. 왜 id는 int, long, Integer가 아닌 Long을 사용할까? 1) int가 아닌 이유 long이 더 많은 값을 저장할 수 있다. (비교) int - 저장 공간: 32 bit - 값의 범위 : -2147483648 ~ 2147483647 long -

joyful-class-maker.tistory.com

 

JpaRepository를 구현하는 Repository 생성

package com.example.stock.repository;

import com.example.stock.entity.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
    Optional<MemberEntity> findByUsername(String username); // 회원 아이디 찾기

    boolean existsByUsername(String username); // 회원 가입 아이디 존재 여부


}

 

Repository를 사용하는 Service 생성

package com.example.stock.service;

import com.example.stock.entity.MemberEntity;
import com.example.stock.model.Auth;
import com.example.stock.repository.MemberRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@AllArgsConstructor
public class MemberService implements UserDetailsService { // Spring security를 사용하기 위해 UserDetailsService 구현

    private final PasswordEncoder passwordEncoder; // Bean으로 정의
    private final MemberRepository memberRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
       return memberRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("couldn't find username")); // orElseThrow로 인해 Optional이 벗겨진다.
    }

    public MemberEntity register(Auth.SignUp member){ // 회원 가입한

        boolean exists = memberRepository.existsByUsername(member.getUsername()); // 아이디가 중복되었는가?

        if(exists){ // 중복이 되지 않은 경우
            throw new RuntimeException("already use username");
        }

        // 비밀번호 암호화 - passwordEncoder
        member.setPassowrd(passwordEncoder.encode(member.getPassowrd()));
        return memberRepository.save(member.toEntity());
    }

    public MemberEntity authenticate(Auth.SingIn member){ // 로그인을 위한 검증
        return null;
    }
}

SpringSecurity를 사용하기 위해 UserDetailService를 구현

loadUserByUsername을 사용해서 Id에 맞는 회원 정보가 존재하는지 확인

 

회원 Entity

package com.example.stock.entity;

import jakarta.persistence.*;
import lombok.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Entity(name = "MEMBER")
@NoArgsConstructor
@Getter
@AllArgsConstructor
@ToString
@Builder
public class MemberEntity implements UserDetails { // Spring Security

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String password;
    
    @ElementCollection
    private List<String> roles;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.roles.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

Spring Security를 사용하기 위해 사용

 

Controller에서 Service로 매개변수로 넘어가는 변수를 모델로 정의

package com.example.stock.model;

import com.example.stock.entity.MemberEntity;
import lombok.Data;

import java.util.List;

public class Auth {

    @Data
    public static class SingIn{
        private String username;
        private String password;
    }

    @Data
    public static class SignUp{
        private String username;
        private String passowrd;
        private List<String> roles; // 권한

        public MemberEntity toEntity(){ // Entity로 변환
            return MemberEntity.builder()
                    .username(username)
                    .password(passowrd)
                    .roles(roles)
                    .build();
        }
    }
}

toEntity가 존재하는 이유?

repository를 사용해서 데이터를 저장하려면 MemberEntitiy 객체가 필요하다. (변환해줘야 한다.)

 

 

 

'Project' 카테고리의 다른 글

[stock] 회원 관리 - 컨트롤러 구현  (0) 2023.09.21
[stock] 회원 관리 - JWT  (0) 2023.09.21
[stock] 캐시 구현  (0) 2023.09.20
[stock] 캐시 - 레디스 구현  (0) 2023.09.19
[stock] 스케줄링  (0) 2023.09.18