Account Entity 생성
@ElementCollection을 붙여 여러게의 enum을 가질 수 있다. 또한 개수가 적고 바로 필요 하므로 fetch를 EAGER로 수정한다.
import lombok.*;
import javax.persistence.*;
import java.util.Set;
@Entity
@Getter @Setter @EqualsAndHashCode(of = "id")
@Builder @NoArgsConstructor @AllArgsConstructor
public class Account {
@Id @GeneratedValue
private Long id;
private String email;
private String password;
@ElementCollection(fetch = FetchType.EAGER) //여러개의 enum을 가질수 있음 기본은 LAZY지만 바로 필요하므로 수정
@Enumerated(value = EnumType.STRING)
private Set<AccountRole> roles;
}
public enum AccountRole {
ADMIN, USER
}
Event 객체에 Account 맵핑
@ManyToOne을 사용하여 Event에서 Account에 단방향으로 매핑할수 있게 한다
@Builder @AllArgsConstructor @NoArgsConstructor
@Getter @Setter @EqualsAndHashCode(of = "id")
@Entity
public class Event {
//...
@ManyToOne
private Account manager;
//...
}
Web Security
보안 인증을 수행, 서블릿 필터 기반
Method Security
메소드가 호출되었을때 인증 권한을 확인, AOP
Security Interceptor
Web Security, Method Security 모두 Security Interceptor를 통해 수행
리소스에 접근을 허용할 것인지 아닌지 결정하는 로직 가짐
SecurityContextHolder
스레드로컬에서 인증정보가 있는지 확인한다
AuthenticationManager
UserDetails Service, Password encoder
Basic Authentication
요청 헤더에 Authentication, Basic, userName+password
UserName에 해당하는 패스워드를 데이터베이스에서 읽어와서 Password encoder로 검사
매칭이되면 Authentication 객체를 만들어 SecrityContextHolder에 저장한다.
AccessDecisionManager
AuthenticationManger에서 인증 후 User의 Role을 기반으로 권한 확인

의존성 추가
pom.xml에 의존성을 추가한다
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
AccountService 생성
UserDetailsService를 상속받아 loadUserByUsername 오버라이딩
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class AccountService implements UserDetailsService {
@Autowired
AccountRepository accountRepository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return null;
}
}
Account를 Spring Security가 정의 한 Interface로 변환
//Account를 Spring Security가 정의 한 Interface로 변환
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByEmail(username).orElseThrow(() -> new UsernameNotFoundException(username));
return new User(account.getEmail(), account.getPassword(), authorities(account.getRoles()));
}
role을 GrantedAuthority로 변환
private Collection<? extends GrantedAuthority> authorities(Set<AccountRole> roles) {
return roles.stream()
.map(r -> new SimpleGrantedAuthority(("ROLE" + r.name())))
.collect(Collectors.toSet());
}
AccountRepository 생성
public interface AccountRepository extends JpaRepository<Account, Long> {
Optional<Account> findByEmail(String username);
}