Spring Security
spring security를 사용하기 위해서 pom.xml에 의존성을 추가해야 한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.2.1</version>
dependency>
그리고 로그인 구현 시 필요한 UserDetailService를 상속받은 service와
UserDetails를 상속받은 User가 필요하다.
UserDetailService
@Service
@RequiredArgsConstructor
public class MemberDetailService implements UserDetailsService {
private final MemberMapper memberMapper;
private final PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String memberId) throws UsernameNotFoundException {
MemberDTO member = memberMapper.getMember(memberId);
if(null != member) {
if(null == member.getAuthority()) {
throw new AuthenticationCredentialsNotFoundException(memberId);
}
return new MemberDetail(member);
} else if(null == member) {
throw new UsernameNotFoundException(memberId);
} else {
throw new BadCredentialsException(memberId);
}
}
}
UserDetails
@RequiredArgsConstructor
public class MemberDetail implements UserDetails {
private final MemberDTO member;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collet = new ArrayList<>();
collet.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_" + member.getAuthority();
}
});
return collet;
}
@Override
public String getPassword() {
return member.getMemberPwd();
}
@Override
public String getUsername() {
return member.getMemberId();
}
public String getAppStatus() {
return member.getAppStatus();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
그리고 제일 중요한 Security 설정 파일인 Security Config 파일을 만든다.
SecurityConfig
public class SecurityConfig {
private final CustomAuthFailureHandler customAuthFailureHandler;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()).cors(cors -> cors.disable())
.authorizeHttpRequests(request -> request
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
.requestMatchers("/resources/**", "/page/signup", "/signup", "/login").permitAll()
.requestMatchers("/page/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(login -> login
.loginPage("/page/login")
.loginProcessingUrl("/page/login")
.defaultSuccessUrl("/page/scheduler", true)
.failureHandler(customAuthFailureHandler)
.permitAll()
)
.logout(Customizer.withDefaults());
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
그리고 login.jsp이다.
Login.jsp
<form action="/page/login" method="post">
<div class="input-group mb-3">
<input type="text" id="memberId" name="username" class="form-control" placeholder="Id">
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-user"></span>
</div>
</div>
</div>
<div class="input-group mb-3">
<input type="password" id="memberPwd" name="password" class="form-control" placeholder="Password">
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-lock"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="submit" class="btn btn-warning btn-block">Sign In</button>
</div>
</div>
</form>
여기서 중요한 점은 login form에 있는 input의 name을 username으로 맞춰줘야
Spring Security가 인식한 후 로그인 과정을 진행할 수 있다.
이거때문에 얼마나 시간을 버렸는지...