Spring Security
Spring Security 보안 강화 기능
Principal : 주체
Authentication : 인증
Authorization : 인가, 권한 부여
Access Control : 접근 제어
보안 강화 위한 솔루션으로 Spring Security만한 프레임워크가 없다
기본 옵션만으로 불가한 특정 보안 요구 사항을 만족시키기 위한 코드 커스터마이징 용이 및 유연한 확장 가능
InMemory 방식 : 테스트환경 혹은 데모환경에서 사용
DB 연동 방식 : Custom UserDetailsService를 사용하는 방법
@Configuration
public class JavaConfiguration {
// 데이터를 DB에 저장, 패스위드 암호화 위한 Memberrepository, PasswordEncoder DI
@Bean
public MemberService dbMemberService(MemberRepository memberRepository,
PasswordEncoder passwordEncoder) {
return new DBMemberService(memberRepository, passwordEncoder);
@Transactional
public class DBMemberService implements MemberService {
// MemberRepository, PasswordEncoder Bean 객체 DI
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
public DBMemberService(MemberRepository memberRepository,
PasswordEncoder passwordEncoder) {
this.memberRepository = memberRepository;
this.passwordEncoder = passwordEncoder;
}
public Member createMember(Member member) {
verifyExistsEmail(member.getEmail());
// PasswordEncoder 사용하여 패스워드 암호화
String encryptedPassword = passwordEncoder.encode(member.getPassword());
// 암호화된 패스워드를 password 필드에 할당
member.setPassword(encryptedPassword);
Member savedMember = memberRepository.save(member);
System.out.println("# Create Member in DB");
return savedMember;
}
...
...
}
// DB의 인증정보로 인증 처리하는 Custom UserDetailsService
@Component
public class HelloUserDetailsService implements UserDetailsService {
private final MemberRepository memberRepository;
private final HelloAuthorityUtils authorityUtils;
public HelloUserDetailsServiceV(MemberRepository memberRepository, HelloAuthorityUtils authorityUtils) {
this.memberRepository = memberRepository;
this.authorityUtils = authorityUtils;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Member> optionalMember = memberRepository.findByEmail(username);
Member findMember = optionalMember.orElseThrow(() -> new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND));
return new HelloUserDetails(findMember)l
}
// DB 조회 회원 정보를 Spring Security의 User 정보로 변환하는 과정, User 권한정보 생성 과정 캡슐화
private final class HelloUserDetails extends Member implememts UserDetails {
HelloUserDetails(Member member) {
setMemberId(member.getMemberId());
setName(member.getName());
setEmail(member.getEmail());
setPassword(member.getPassword());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorityUtils.createAuthorities(this.getEmail());
}
@Override
public String getUsername() {
return getEmail();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
}
// User 권한 매핑, 생성하는 HelloAuthorityUtils
@Component
public class HelloAuthorityUtils {
// .yml 추가 프로퍼티 가져오는 표현식
// @Value("${프로퍼티_경로}")
// 사용 전 .yml파일에 관리자 이메일 주소 정의 필요
@Value("${mail.address.admin}")
private String adminMailAddress;
// AuthorityUtils 클래스 사용하여 관리자용 권한 목록 생성
private final List<GrantedAuthority> ADMIN_ROLES = AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ROLE_USER");
// AuthorityUtils 클래스 사용하여 일반 사용 권한 목록 생성
private final List<GrantedAuthority> USER_ROLES = AuthorityUtils.createAuthorityList("ROLE_USER");
public List<GrantedAuthority> createAuthorities(String email) {
// 매개변수 email과 .yml파일의 이메일과 동일하다면 관리자용 권한 리턴
if (email.equals(adminMailAddress)) {
return ADMIN_ROLES;
}
return USER_ROLES;
}
}