인증(Authentication), 인가(Authorization)를 하기 위해 Spring security 사용
Initializr로 생성할 때 security -> spring security 선택.
또는 pom.xml에 spring-boot-starter-security 의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
의존성을 추가하고 external libraries에 가보면 시큐리티 관련 의존성들이 포함된 것을 볼 수 있음.
WebSecurityConfigurerAdapter에 정의된 메서드들을 override해서 쉽게 인증,인가 설정 가능
override configure(AuthenticationManagerBuilder)
override configure(HttpSecurity)
PasswordEncoder
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//직접 Authentication Manager를 설정할 수 있도록 해주는 cofigure(매니저빌더) 메서드도 있다.
//UserDetailsService를 구현한 클래스를 따로 만들었으면 이 부분은 사용하지 않음.
//특정 URL(리소스)에 접근 제한 설정하기
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/reserve").hasRole("USER");
http.formLogin();
http.csrf().disable();
http.logout();
}
}
DB에서 사용자 정보를 꺼내와야 하기 때문에 JPA repository 필요.
따라서 Entity class,MemberRepository를 작성. 그리고 userDetailsService를 implements한 service 클래스,
User 클래스를 extends하여 만든 DTO도 작성.
//entity
@Getter
@ToString
@NoArgsConstructor
@Entity
public class Member {
@Id
private String email;
private String password;
private String name;
@Enumerated(value = EnumType.STRING)
private MemberRole memberRole;
@Builder
public Member(String email, String name,String password) {
this.email = email;
this.name = name;
this.password = password;
}
public void setMemberRole(MemberRole memberRole) {
this.memberRole = memberRole;
}
}
//dto
@ToString
@Getter
@Setter
public class MemberDTO extends User {
private String email;
private String name;
public MemberDTO(String username, String password,
Collection<? extends GrantedAuthority> authorities){
super(username,password,authorities);
this.email = username;
}
}
//repository layer
public interface MemberRepository extends JpaRepository<Member,String> {
Optional<Member> findByEmail(String email);
}
//user type
public enum MemberRole {
USER("USER"),ADMIN("ADMIN");
private final String typeName;
private MemberRole(String typeName){
this.typeName = typeName;
}
public String getTypeName(){
return typeName;
}
}
//service layer
@Service
public class MemberDetailsService implements UserDetailsService {
@Autowired
private MemberRepository memberRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Member> result = memberRepository.findByEmail(username);
if (result.isPresent() == false) {
throw new UsernameNotFoundException("user not found");
}
Member member = result.get();
Collection<SimpleGrantedAuthority> authList = new ArrayList<>();
authList.add(new SimpleGrantedAuthority("ROLE_"+member.getMemberRole().getTypeName()));
MemberDTO dto = new MemberDTO(member.getEmail(),member.getPassword(),authList);
dto.setName(member.getName());
return dto;
}
}