From 25cdf48f13ad41b3e59c9e48146c91d83d138842 Mon Sep 17 00:00:00 2001 From: icksishu Date: Tue, 17 Jun 2025 22:45:35 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=B0=8F=20=EC=B2=98=EB=A6=AC=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=A4=91=20=20-=20=ED=99=94=EB=A9=B4=EC=9D=80=20vue=EB=A1=9C?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1=20=20-=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EB=8A=94=20ajax=EB=A1=9C=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/front/index.html | 7 ++- src/main/front/index.html.bak | 13 +++++ src/main/front/src/App.vue | 35 +++++--------- src/main/front/src/App.vue.bak | 30 ++++++++++++ src/main/front/src/assets/css/login.css | 39 +++++++++++++++ src/main/front/src/components/ConsoleMain.vue | 43 +++++++++++++++++ src/main/front/src/components/LoginView.vue | 47 +++++++++++++++++++ ...nUsernamePasswordAuthenticationFilter.java | 34 ++++++++++++++ .../framework/config/SecurityConfig.java | 20 +++++++- 9 files changed, 242 insertions(+), 26 deletions(-) create mode 100644 src/main/front/index.html.bak create mode 100644 src/main/front/src/App.vue.bak create mode 100644 src/main/front/src/assets/css/login.css create mode 100644 src/main/front/src/components/ConsoleMain.vue create mode 100644 src/main/front/src/components/LoginView.vue create mode 100644 src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/JsonUsernamePasswordAuthenticationFilter.java diff --git a/src/main/front/index.html b/src/main/front/index.html index 8388c4b..e61b9b3 100644 --- a/src/main/front/index.html +++ b/src/main/front/index.html @@ -1,10 +1,13 @@ - + + + - Vite + Vue + + Dfx console
diff --git a/src/main/front/index.html.bak b/src/main/front/index.html.bak new file mode 100644 index 0000000..8388c4b --- /dev/null +++ b/src/main/front/index.html.bak @@ -0,0 +1,13 @@ + + + + + + + Vite + Vue + + +
+ + + diff --git a/src/main/front/src/App.vue b/src/main/front/src/App.vue index 81c28ec..93feecd 100644 --- a/src/main/front/src/App.vue +++ b/src/main/front/src/App.vue @@ -1,30 +1,21 @@ diff --git a/src/main/front/src/App.vue.bak b/src/main/front/src/App.vue.bak new file mode 100644 index 0000000..81c28ec --- /dev/null +++ b/src/main/front/src/App.vue.bak @@ -0,0 +1,30 @@ + + + + + diff --git a/src/main/front/src/assets/css/login.css b/src/main/front/src/assets/css/login.css new file mode 100644 index 0000000..4732d1f --- /dev/null +++ b/src/main/front/src/assets/css/login.css @@ -0,0 +1,39 @@ +html, +body { + height: 100%; +} + +body { + display: flex; + align-items: center; + padding-top: 40px; + padding-bottom: 40px; + background-color: #f5f5f5; +} + +.form-signin { + width: 100%; + max-width: 330px; + padding: 15px; + margin: auto; +} + +.form-signin .checkbox { + font-weight: 400; +} + +.form-signin .form-floating:focus-within { + z-index: 2; +} + +.form-signin input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.form-signin input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} diff --git a/src/main/front/src/components/ConsoleMain.vue b/src/main/front/src/components/ConsoleMain.vue new file mode 100644 index 0000000..546ebbc --- /dev/null +++ b/src/main/front/src/components/ConsoleMain.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/main/front/src/components/LoginView.vue b/src/main/front/src/components/LoginView.vue new file mode 100644 index 0000000..121206a --- /dev/null +++ b/src/main/front/src/components/LoginView.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/JsonUsernamePasswordAuthenticationFilter.java b/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/JsonUsernamePasswordAuthenticationFilter.java new file mode 100644 index 0000000..662d538 --- /dev/null +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/JsonUsernamePasswordAuthenticationFilter.java @@ -0,0 +1,34 @@ +package com.bsmlab.dfx.dfxconsole.framework.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import java.io.IOException; +import java.util.Map; + +public class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { + @SuppressWarnings("unchecked") + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + if(!request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) { + throw new IllegalArgumentException("not application/json"); + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + Map userInfoMap = objectMapper.readValue(request.getInputStream(), Map.class); + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userInfoMap.get("username"), userInfoMap.get("password")); + this.setDetails(request, usernamePasswordAuthenticationToken); + return this.getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken); + } + catch(IOException e) { + throw new AuthenticationServiceException("사용자 정보를 확인할 수 없습니다."); + } + } +} diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/SecurityConfig.java b/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/SecurityConfig.java index d78292a..218c797 100644 --- a/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/SecurityConfig.java +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/framework/config/SecurityConfig.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; 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.configurers.AbstractHttpConfigurer; @@ -11,6 +12,7 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Slf4j @Configuration @@ -18,8 +20,8 @@ import org.springframework.security.web.SecurityFilterChain; @RequiredArgsConstructor public class SecurityConfig { - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { + //@Bean + public SecurityFilterChain securityFilterChainFormLogin(HttpSecurity httpSecurity) throws Exception { httpSecurity .csrf(AbstractHttpConfigurer::disable) // REST API 를 제공하는 서비스이므로 Cross Site Request Forgery disable .authorizeHttpRequests(authorize -> authorize @@ -44,6 +46,20 @@ public class SecurityConfig { return httpSecurity.build(); } + @Bean + public SecurityFilterChain securityFilterChainAjax(HttpSecurity httpSecurity) throws Exception { + JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter(); + jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(httpSecurity.getSharedObject(AuthenticationManager.class)); + jsonUsernamePasswordAuthenticationFilter.setFilterProcessesUrl("/public-api/loginProcess"); + httpSecurity + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorize -> authorize.requestMatchers("/app-api/**").hasRole("USER").anyRequest().permitAll()) + .addFilterAt(jsonUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) + .sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(false)) + ; + return httpSecurity.build(); + } + @Bean public PasswordEncoder getPasswordEncoder() { return new BCryptPasswordEncoder();