[3강]
@Autowired
private UserRepository userRepository;
@PostMapping({"/join"}) //securityConfig 파일 생성 후 작동안함.
public String join(User user) {
System.out.println(user);
user.setRole("ROLE_USER");
String rowPassword = user.getPassword();
String encPassword = bCryptPasswordEncoder.encode(rowPassword);
user.setPassword(encPassword);
userRepository.save(user);
return "redirect:/loginForm";
}
위의 과정은 로그인 form에서 비밀번호가 db에 그대로 저장되지 않고, 암호화를 해서 저장할 수 있도록 하는 코드이다.
생각보다 더 간단해서 놀랐다.
[4강]
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/user/**").authenticated()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/loginForm")
***.loginProcessingUrl("/login")
.defaultSuccessUrl("/");
}
***.loginProcessingUrl("/login")
"/login" 주소가 호출이 되면 시큐리티가 낚아채서 대신 로그인을 진행한다.
그래서 controller에 "/login"에 대한 정의를 따로 할 필요가 없음.
< PrincipalDetails 클래스의 정의 >
public class PrincipalDetails implements UserDetails {
- 시큐리티가 "/login" 주소 요청이 오면 낚아채서 진행시킨다.
- 로그인이 진행 완료되면 시큐리티가 시큐리티만의 자체 session을 만들어준다. (Security ContextHolder)
- 그런데 이 세션에 접근하기 위해서는 특정 오브젝트로 접근할 수 있는데....
오브젝트 타입 => Authentication 타입 객체 - Authentication 안에 User 정보가 있어야 됨.
- User 오브젝트타입 => UserDatails 타입 객체
Security Session -> Authentication -> UserDetails(PrincipalDetails)
< UserDetails 인터페이스 내부에 있는 함수 중 하나 >
public class PrincipalDetails implements UserDetails {
private User user; // 콜포지션
public PrincipalDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() { //해당 user의 권한을 리턴하는 곳!!
Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRole();
}
});
return collection;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
.
.
.(생략)
❓getAuthorities() 이란 함수는 단순히 사용자의 권한을 리턴해주는 함수인데 왜 return user.getRole()이 아닐까?
UserDetails에 있는 함수를 구현해야 하고, 거기에서 정해놓은 형식이 반환형이 Collection<? extends GrantedAuthority> 타입이기 때문에 반드시 그 규격을 따라야 한다. 따라서 return user.getRole()을 하면 반환형이 String 이기 때문에 안된다.
(collection.add(new GrantedAuthority() 를 치면 알아서 아래의 구조가 자동완성된다.) - 물론 return 값은 개발자가 직접 지정.
< UserDetailsService의 구현 클래스 >
// 시큐리티 설정에서 loginProcessingUrl("/login"); 에서 이 클래스가 발동
@Service
public class PrincipalDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user != null){
return new PrincipalDetails(user);
}
return null;
}
}
- 시큐리티 session (내부 Authentication (내부 UserDetials))로 해당 메서드의 반환 값이 전달된다.
❗loadUserByUsername 함수를 사용할 때 주의점은?
loadUserByUsername 메서드의 인자 이름을 username으로 일치시켜야 합니다. Spring Security는 이 메서드가 호출될 때, 로그인 폼에서 입력한 아이디(username)를 자동으로 전달해 줍니다.
❓UserDetailsService와 UserDetails의 차이점
UserDetailsService
- UserDetailsService 인터페이스는 Spring security가 사용자 정보를 어떻게 가져올지를 정의한 인터페이스이다.
- 이 인터페이스를 구현한 클래스는 loadUserByUsername 메서드를 제공해야 한다.
- 이 메서드는 사용자의 아이디(username)를 기반으로 사용자 정보를 검색하고, 이를 UserDetails 객체로 반환.
UserDetails
- UserDetails 인터페이스는 Spring Security에서 사용자의 세부 정보를 표현하기 위한 인터페이스이다.
정리하자면, UserDetailsService는 Spring Security가 사용자 정보를 어디서 가져올지를 결정하고 UserDetails는 사용자 정보를 표현하고 저장하는 역할을 한다.

'개발공부 > spring security & JWT 강의' 카테고리의 다른 글
[6강] 구글 로그인 준비 (0) | 2023.09.22 |
---|---|
[5강] 메소드 단위로 권한 설정하기 - @Secured (0) | 2023.09.21 |
[4강] 스프링 시큐리티 로그인 구현 - '?error' 발생 (0) | 2023.09.20 |
[2강] spring security 설정 (예제) (0) | 2023.09.15 |
[1강] spring security 환경설정 &⭐새로운 사실 (0) | 2023.09.15 |