사실 전 챕터에서 이번 챕터로 넘어오면서 많은 코드를 작성하였습니다.
DTO도 각 상황에 맞게 만들었고 서비스 코드나 예외 처리도 추가하였습니다.
따라하시는 분이 있다면 어렵지 않은 코드들이니 제 GitHub에 오셔서 코드 보시면 도움이 될 것 같습니다!
implementation 'org.springframework.boot:spring-boot-starter-security'
@Configuration
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filerChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.authorizeHttpRequests(request-> request
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
.requestMatchers("/api/users/**","/status/**","/h2-console/**").permitAll()
.anyRequest().authenticated()
)
.headers(header -> header
.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)
) //h2-console관련
.formLogin(login -> login
.usernameParameter("email")
.passwordParameter("password")
.failureForwardUrl("/status/fail")
.defaultSuccessUrl("/status/ok",true)
.permitAll()
)
.logout(Customizer.withDefaults());
return http.build();
}
}
spring security 3.0으로 넘어오면서 기존의 Adapter 방식이 변경되었습니다.
requestMatchers의 값들은 필요하신대로 추가/삭제 하시면되고
저는 id 값으로 email값을 사용해주었습니다.
@RestController
@RequestMapping("/status")
public class CheckController {
@GetMapping("/ok")
public String check() {
return "ok";
}
@PostMapping("/fail")
public ApiResponse<String> loginFail() {
return ApiResponse.onFailure("401", "login fail", "fail");
}
}
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Builder
public class Users extends BaseEntity implements UserDetails {
...
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getUsername() {
return this.email;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
이제 준비는 끝났고 로그인하는 로직에 관해 구현해보겠습니다.
@Component
@RequiredArgsConstructor
public class MyUserDetailService implements UserDetailsService {
private final UserService userService;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Users user = userService.getUserByEmail(email);
return User.builder()
.username(user.getEmail())
.password(user.getPassword())
.roles("USER")
.build();
}
}
먼저 저는 따로 암호화 없이 raw password로 검증하게 했습니다.
public class SimplePaaswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(encode(rawPassword));
}
}
@Configuration
public class SpringSecurityConfig {
...
@Bean
PasswordEncoder passwordEncoder() {
return new SimplePaaswordEncoder();
}
}