회원가입에 필요한 라이브러리를 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 |