Spring Framework-17

🗄 이번엔 인메모리 방식이 아닌 DB에서 유저를 가져와 인증해봅시다!


CustomUserDetailServiceImpl 추가

Spring Security에서는 UserDetailService를 이용하여 유저를 조회합니다. 우리는 이를 구현하는 클래스를 만듭니다. 우리의 usernameemail이므로 userMapper가 파라미터로 들어온 email로 유저를 조회하여 반환할 수 있도록 만듭니다.

@Service
@RequiredArgsConstructor
public class CustomUserDetailServiceImpl implements UserDetailsService {
    private final UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return userMapper.findByEmail(s);
    }
}

UserVO 수정

UserDetailService가 반환하는 클래스는 UserDetails입니다. 따라서 UserVO가 이를 구현하는 클래스로 수정합니다. UserDetails는 반드시 권한을 가져야합니다. 따라서 일단 ROLE_USER를 넣어 반환하겠습니다.

@Data
public class UserVO implements UserDetails {
    private int id;
    private String name;
    private String password;
    private String email;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
    }
    /*
    * Spring Security의 username을 반환
    */
    @Override
    public String getUsername() {
        return email;
    }

    /*
    * 계정이 만료되었는가?
    * */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /*
    * 계정이 잠겼는가?
    * */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    /*
    * 계정의 인증(비밀번)이 만료되었는가?
    * */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /*
    * 계정이 사용가능한가?
    * */
    @Override
    public boolean isEnabled() {
        return true;
    }
}

SecurityConfig 수정

우리는 이제 인메모리 방식이 아닌 커스텀된 UserDetailService를 사용해 유저를 조회합니다. Spring Security는 반드시 PasswordEncoder를 사용해야해 이를 생성하고 반환하는 메소드를 @Bean으로 만들어줍니다. 여기서 PasswordEncoderFactories.createDelegatingPasswordEncoder()는 기본적으로 BCRYPT 인코딩입니다딩

 @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

UserService 수정

비밀번호를 확인하는 메소드는 필요가 없으므로 주석처리하고, 유저의 정보를 저장할 때 비밀번호를 인코딩하여 저장할 수 있도록 수정합니다.

public interface UserService {
    public void save(UserVO userVO);
    public boolean checkEmailDuplication(String email);
//    public boolean checkPassword(String email, String password);
    public UserVO findByEmail(String email);
}
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    @Override
    public void save(UserVO userVO) {
        userVO.setPassword(passwordEncoder.encode(userVO.getPassword()));
        userMapper.save(userVO);
    }

    @Override
    public boolean checkEmailDuplication(String email) {
        return userMapper.checkEmailDuplication(email)==0;
    }

//    @Override
//    public boolean checkPassword(String email, String password) {
//        return password.equals(userMapper.findByEmail(email).getPassword());
//    }

    @Override
    public UserVO findByEmail(String email) {
        return userMapper.findByEmail(email);
    }

}

DB 수정

인코딩한 비밀번호는 길어서 user 테이블의 password의 길이를 늘려줍니다. 그리고 이미 있는 user는 모두 삭제해야 하므로 저장되있던 데이터를 모두 삭제합니다.

alter table user modify password varchar(100);
delete from file;
delete from post;
delete from user;

테스트




좋은 웹페이지 즐겨찾기