해당 글은 groomedu의 스프링부트 나만의 블로그 만들기 강의를 보고 개인적으로 정리한 글입니다.
loginForm.jsp
<form action="/auth/loginProc" method="post">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" placeholder="Enter username" id="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" placeholder="Enter password" id="password">
</div>
<button id="btn-login" class="btn btn-primary">로그인</button>
</form>
로그인 버튼 클릭 시 form action 주소로 이동한다.
UserApiController에 '/auth/loginProc'에 POST 매핑되는 메소드를 선언하지 않고
스프링 시큐리티에서 가로채기 하게 한다.
SpringConfig.java
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // csrf 토큰 비활성화
.authorizeRequests()
.requestMatchers("/**", "/auth/**", "/js/**", "/css/**", "/image/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/auth/loginForm")
.loginProcessingUrl("/auth/loginProc")// 스프링 시큐리티가 해당 주소로 요청오는 로그인을 가로채서 대신 로그인 해준다.
.defaultSuccessUrl("/");//로그인이 성공하면 "/" 경로로 이동
return http.build();
}
.loginProcessingUrl("/auth/loginProc")// 스프링 시큐리티가 해당 주소로 요청오는 로그인을 가로채서 대신 로그인 해준다.
.defaultSuccessUrl("/");//로그인이 성공하면 "/" 경로로 이동
.loginProcessingUrl() : 스프링 시큐리티가 () 안에 주소로 요청이 오는 로그인을 가로채서 로그인
.defaultSuccessUrl() : 정상 요청 시 () 안에 주소로 이동
로그인 시에 이름과 비밀번호를 입력받아서 DB에 있는지 확인해야한다.
로그인 진행 후 UserDetails 타입의 오브젝트를 세션저장소에 저장해야하기 때문에 UserDetails 선언 필요
PrincipalDetail (UserDetails 타입의 오브젝트)
public class PrincipalDetail implements UserDetails{
private User user; // 콤포지션: 객체를 품고 있는 것.
public PrincipalDetail(User user) {
this.user = user;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
// 계정이 만료되지 않았는지 리턴한다.(true:만료안됨)
@Override
public boolean isAccountNonExpired() {
return true;
}
// 계정이 잠겨있는지 아닌지 리턴한다.(true:잠기지 않음)
@Override
public boolean isAccountNonLocked() {
return true;
}
// 비밀번호가 만료됐는지 안 됐는지 리턴한다.(true:만료 안 됨)
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 계정이 활성화(사용가능)인지 리턴한다. (true:활성화)
@Override
public boolean isEnabled() {
return true;
}
// 계정의 권한 목록을 리턴한다.
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collectors = new ArrayList<>();
// GrantedAuthority 인터페이스에 메소드는 getAuthority() 하나이기에 아래와 같이 람다식으로 선언가능
collectors.add(()->{return "ROLE_"+user.getRole();});
return collectors;
}
}
getAuthorties() : 계정의 권한 목록을 리턴함
스프링은 권한이 “ROLE_”로 시작하기 때문에 붙여서 리턴
람다식을 사용하여 collectors에 권한을 add하여 리턴
PrincipalDetailService
@Service
public class PrincipalDetailService implements UserDetailsService{
@Autowired
private UserRepository userRepository;
// 스프링이 로그인 요청을 가로챌때, username, password 변수 2를 가로채는데
// password 부분은 알아서 함.
// username이 DB에 있는지만 확인해주면 됨.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User principal = userRepository.findByUsername(username)
.orElseThrow(()->{
return new UsernameNotFoundException("해당 사용자를 찾을 수 없습니다. :"+username);
});
return new PrincipalDetail(principal); //시큐리티의 세션에 유저 정보가 저장이 됨.
}
}
loadUserByUsername() 함수에서 DB에 username이 있는지 체크
password가 틀린 것은 스프링 시큐리티에서 알아서 처리
리턴하는 PrincipalDetail(UserDetails 타입의 유저 정보)가 스프링 시큐리티 세션에 저장됨.
SecurityConfig
// 시큐리티가 대신 로그인 해주는데 password를 가로채기 하는데
// 해당 password가 뭘로 해쉬 되어 회원가입이 되었는지 알아야
// 같은 해쉬로 암호화해서 DB에 있는 해쉬랑 비교할 수 있음.
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(principalDetailService).passwordEncoder(encodePWD());
}
configure() 함수를 선언하여 입력 받은 비밀번호를 해쉬화한 값과 DB에 저장된 값과 비교한다.
** 이 부분은 스프링 최신 버전에서는 DI한 SecurityFilterchain에서 자동으로 PrincipalDetailService를 불러와서 비교하므로 제거
로그인 정보를 입력 후 성공하면 우측 화면과 같이 메뉴가 바뀐 것을 확인할 수 있다.
'Spring > SpringBoot' 카테고리의 다른 글
[goormedu 강의] 스프링부트 블로그 만들기 06 - 04 XSS와 CSRF (0) | 2024.10.05 |
---|---|
[goormedu 강의] 스프링부트 블로그 만들기 06 - 03 비밀번호 해쉬 후 회원가입하기 (0) | 2024.10.05 |
[goormedu 강의] 스프링부트 블로그 만들기 06 - 02 스프링 시큐리티 로그인 페이지 커스터마이징 (0) | 2024.09.25 |
[goormedu 강의] 스프링부트 블로그 만들기 06 - 01 스프링 시큐리티 체험해보기 (0) | 2024.09.25 |
[goormedu 강의] 스프링부트 블로그 만들기 05 - 12 전통적인 방식의 로그인 방법 (1) | 2024.08.30 |