|
|
|
@ -5,10 +5,13 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
|
|
|
|
|
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
|
|
|
|
|
|
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
|
|
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
|
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
|
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
|
|
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
|
|
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
|
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
|
|
|
|
|
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
|
|
import org.springframework.security.web.SecurityFilterChain;
|
|
|
|
import org.springframework.security.web.SecurityFilterChain;
|
|
|
|
@ -31,12 +34,12 @@ public class SecurityConfig {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.formLogin(form -> form
|
|
|
|
.formLogin(form -> form
|
|
|
|
.loginPage("/login.html")
|
|
|
|
.loginPage("/login.html")
|
|
|
|
.loginProcessingUrl("/loginProcess")
|
|
|
|
.loginProcessingUrl("/public-api/loginProcess")
|
|
|
|
.defaultSuccessUrl("/index.html")
|
|
|
|
.defaultSuccessUrl("/index.html")
|
|
|
|
.permitAll()
|
|
|
|
.permitAll()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.logout(logout -> logout
|
|
|
|
.logout(logout -> logout
|
|
|
|
.logoutUrl("/logout")
|
|
|
|
.logoutUrl("/public-api/logoutProcess")
|
|
|
|
.logoutSuccessUrl("/login.html")
|
|
|
|
.logoutSuccessUrl("/login.html")
|
|
|
|
.invalidateHttpSession(true)
|
|
|
|
.invalidateHttpSession(true)
|
|
|
|
.deleteCookies("JSESSIONID")
|
|
|
|
.deleteCookies("JSESSIONID")
|
|
|
|
@ -46,15 +49,31 @@ public class SecurityConfig {
|
|
|
|
return httpSecurity.build();
|
|
|
|
return httpSecurity.build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
1. 사용자가 POST /public-api/loginProcess 요청 (username, password)
|
|
|
|
|
|
|
|
2. JsonUsernamePasswordAuthenticationFilter → attemptAuthentication()
|
|
|
|
|
|
|
|
3. UsernamePasswordAuthenticationToken 생성
|
|
|
|
|
|
|
|
4. AuthenticationManager → DaoAuthenticationProvider로 위임
|
|
|
|
|
|
|
|
5. DaoAuthenticationProvider
|
|
|
|
|
|
|
|
├─ AppUserDetailsService.loadUserByUsername() 호출
|
|
|
|
|
|
|
|
├─ UserDetails.getPassword() ← 암호화된 비밀번호
|
|
|
|
|
|
|
|
├─ 입력값 password 와 비교: passwordEncoder.matches(raw, encoded)
|
|
|
|
|
|
|
|
└─ 성공 or 실패
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
|
public SecurityFilterChain securityFilterChainAjax(HttpSecurity httpSecurity) throws Exception {
|
|
|
|
public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
|
|
|
|
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter();
|
|
|
|
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter();
|
|
|
|
jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(httpSecurity.getSharedObject(AuthenticationManager.class));
|
|
|
|
jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager);
|
|
|
|
jsonUsernamePasswordAuthenticationFilter.setFilterProcessesUrl("/public-api/loginProcess");
|
|
|
|
jsonUsernamePasswordAuthenticationFilter.setFilterProcessesUrl("/public-api/loginProcess");
|
|
|
|
|
|
|
|
return jsonUsernamePasswordAuthenticationFilter;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
|
|
|
public SecurityFilterChain securityFilterChainAjax(HttpSecurity httpSecurity, AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
|
|
|
httpSecurity
|
|
|
|
httpSecurity
|
|
|
|
.csrf(AbstractHttpConfigurer::disable)
|
|
|
|
.csrf(AbstractHttpConfigurer::disable)
|
|
|
|
.authorizeHttpRequests(authorize -> authorize.requestMatchers("/app-api/**").hasRole("USER").anyRequest().permitAll())
|
|
|
|
.authorizeHttpRequests(authorize -> authorize.requestMatchers("/app-api/**").authenticated().anyRequest().permitAll())
|
|
|
|
.addFilterAt(jsonUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
|
|
|
.addFilterAt(this.jsonUsernamePasswordAuthenticationFilter(this.authenticationManager(authenticationConfiguration)), UsernamePasswordAuthenticationFilter.class)
|
|
|
|
.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(false))
|
|
|
|
.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(false))
|
|
|
|
;
|
|
|
|
;
|
|
|
|
return httpSecurity.build();
|
|
|
|
return httpSecurity.build();
|
|
|
|
@ -70,4 +89,17 @@ public class SecurityConfig {
|
|
|
|
return new GrantedAuthorityDefaults(""); // "ROLE_" prefix 를 제거한다.
|
|
|
|
return new GrantedAuthorityDefaults(""); // "ROLE_" prefix 를 제거한다.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
|
|
|
public DaoAuthenticationProvider daoAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
|
|
|
|
|
|
|
|
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
|
|
|
|
|
|
|
|
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
|
|
|
|
|
|
|
|
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
|
|
|
|
|
|
|
|
return daoAuthenticationProvider;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
|
|
|
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
|
|
|
|
|
|
|
return authenticationConfiguration.getAuthenticationManager();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|