로그인 화면 및 처리 변경중

- 화면은 vue로 구성
 - 로그인 처리는 ajax로 구성
main
icksishu 7 months ago
parent abebbd4924
commit 25cdf48f13

@ -1,10 +1,13 @@
<!doctype html>
<html lang="en">
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<title>Dfx console</title>
</head>
<body>
<div id="app"></div>

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

@ -1,30 +1,21 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import {onMounted} from 'vue'
import LoginView from './components/LoginView.vue'
import ConsoleMain from './components/ConsoleMain.vue'
let hasSession = false;
function isHasSession() {
return false;
}
onMounted(() => {
hasSession = isHasSession();
});
</script>
<template>
<div>
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
<ConsoleMain v-if="hasSession"></ConsoleMain>
<LoginView v-else></LoginView>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

@ -0,0 +1,30 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<div>
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

@ -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;
}

@ -0,0 +1,43 @@
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
>create-vue</a
>, the official Vue + Vite starter
</p>
<p>
Learn more about IDE Support for Vue in the
<a
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
target="_blank"
>Vue Docs Scaling up Guide</a
>.
</p>
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>

@ -0,0 +1,47 @@
<script setup>
import '../assets/css/login.css'
// ajax login check
</script>
<template>
<main class="form-signin">
<form method="post" action="/loginProcess">
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input type="text" name="username" class="form-control" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" name="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">&copy; 20172021</p>
</form>
</main>
</template>
<style scoped>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>

@ -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<String, String> 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("사용자 정보를 확인할 수 없습니다.");
}
}
}

@ -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();

Loading…
Cancel
Save