vue2_frontend...

This commit is contained in:
최준흠 2022-09-15 17:34:10 +09:00
parent 22543d0f15
commit 8da393dd29
15 changed files with 215 additions and 148 deletions

View File

@ -80,13 +80,10 @@ export default {
getValidationState({ dirty, validated, valid = null }) {
return dirty || validated ? valid : null
},
onSubmit() {
async onSubmit() {
try {
authService.login({
email: this.form.email,
password: this.form.password
})
this.$router.push({
await authService.login(this.form.email, this.form.password)
await this.$router.push({
name: this.$route.params.return_url || 'home'
})
} catch (e) {

View File

@ -136,14 +136,14 @@
</div>
</template>
<script>
import createNamespacedHelpers from 'vuex'
import todoService from '@/service/todo.service'
import { createNamespacedHelpers } from 'vuex'
const todoStore = createNamespacedHelpers('TodoStore')
const store = createNamespacedHelpers('TodoStore')
// : https://vuejsexamples.com/vuejs-tables-and-select-all-checkbox/
export default {
components: {},
computed: {
...todoStore.mapGetters(['getTotal', 'getRows'])
...store.mapGetters(['getTotal', 'getRows'])
},
created: function () {
this.setDatas()

View File

@ -1,45 +1,32 @@
import api from './auth.api'
import jwt from '../service/jwt'
import authApi from './auth.api'
import tokenService from '../service/token.service'
//참조: https://www.bezkoder.com/vue-refresh-token/
const setup = (store) => {
//API Request 전 처리용
api.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
//Request 처리용
api.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
authApi.interceptors.request.use(
(config) => {
const token = tokenService.getLocalAccessToken()
if (token) {
// config.headers["Authorization"] = 'Bearer ' + token; // for Spring Boot back-end
config.headers['x-access-token'] = token // for Node.js Express back-end
}
return config
},
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await api
.post('/auth/reload', {
refresh_token: jwt.getRefreshToken()
})
.then((rs) => {
store.dispatch('reload', rs.data.access_token)
})
return api(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
//Response 처리용
api.interceptors.response.use(
authApi.interceptors.response.use(
(response) => {
console.log('AUTH API Call 성공=>' + response)
return response
},
async (err) => {
// Do something with response error
//err.config->이전에 보냈던 api (url등)정보 전달용
//err.response->오류 상태를 알기 위해
//originalConfig._retry는 처음 시도용인지 알기 위해
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
@ -49,5 +36,27 @@ const setup = (store) => {
return Promise.reject(err)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await authApi
.post('/auth/reload', {
refresh_token: tokenService.getLocalRefreshToken()
})
.then((rs) => {
const { access_token } = rs.data
store.dispatch('reload', access_token)
tokenService.updateLocalAccessToken(access_token)
})
//reload로 access_token을 재발급을 받았으면 이전 APICall 다시 호출
return await authApi(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
}
export default setup

View File

@ -1,7 +1,5 @@
import axios from 'axios'
const authAPI = axios.create({
baseURL: process.env.VUE_APP_AUTH_HOST,
headers: { 'Content-type': 'application/json' }
const authApi = axios.create({
baseURL: process.env.VUE_APP_AUTH_HOST
})
export default authAPI
export default authApi

View File

@ -0,0 +1,70 @@
import axios from 'axios'
import authApi from './auth.api'
import tokenService from '../service/token.service'
//참조: https://www.bezkoder.com/vue-refresh-token/
const interceptor = () => {
//API Request 전 처리용
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
axios.defaults.headers.get['Accepts'] = 'application/json'
axios.defaults.timeout = 2500
//Request 처리용
axios.interceptors.request.use(
(config) => {
const token = tokenService.getLocalAccessToken()
if (token) {
config.headers['Authorization'] = 'Bearer ' + token // for Spring Boot back-end
config.headers['x-access-token'] = token // for Node.js Express back-end
}
return config
},
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//Response 처리용
axios.interceptors.response.use(
(response) => {
return response
},
async (err) => {
//err.config->이전에 보냈던 api (url등)정보 전달용
//err.response->오류 상태를 알기 위해
//originalConfig._retry는 처음 시도용인지 알기 위해
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
return await reloadAccessToken(originalConfig)
}
}
return Promise.reject(err)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await authApi
.post('/auth/reload', {
refresh_token: tokenService.getLocalRefreshToken()
})
.then((rs) => {
const { access_token } = rs.data
tokenService.updateLocalAccessToken(access_token)
})
//reload로 access_token을 재발급을 받았으면 이전 APICall 다시 호출
return await axios(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
}
export default interceptor

View File

@ -1,58 +1,63 @@
import api from './auth.api'
import jwt from '../service/jwt'
import todoApi from './todo.api'
import authApi from './auth.api'
import tokenService from '../service/token.service'
//참조: https://www.bezkoder.com/vue-refresh-token/
const setup = (store) => {
//API Request 전 처리용
api.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded'
//Request 처리용
api.interceptors.request.use(
(config) => jwt.getAuthorizationHeader(config),
todoApi.interceptors.request.use(
(config) => {
const token = tokenService.getLocalAccessToken()
if (token) {
// config.headers["Authorization"] = 'Bearer ' + token; // for Spring Boot back-end
config.headers['x-access-token'] = token // for Node.js Express back-end
}
return config
},
(error) => {
// Do something with request error
Promise.reject(error)
}
)
//Response 처리용
todoApi.interceptors.response.use(
(response) => {
return response
},
async (err) => {
//err.config->이전에 보냈던 api (url등)정보 전달용
//err.response->오류 상태를 알기 위해
//originalConfig._retry는 처음 시도용인지 알기 위해
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
return await reloadAccessToken(originalConfig)
}
}
return Promise.reject(err)
}
)
//AccessToken이 만료된경우 다시 받기위한 함수
const reloadAccessToken = async (originalConfig) => {
// Access Token이 expired,오류로 인한 response 401 답볍을 받은경우
originalConfig._retry = true
try {
//Refresh Token으로 다시 Access Token 재생성 후 로그인 다시하라고 오류보냄
await api
await authApi
.post('/auth/reload', {
refresh_token: jwt.getRefreshToken()
refresh_token: tokenService.getLocalRefreshToken()
})
.then((rs) => {
store.dispatch('reload', rs.data.access_token)
const { access_token } = rs.data
store.dispatch('reload', access_token)
tokenService.updateLocalAccessToken(access_token)
})
return api(originalConfig)
//reload로 access_token을 재발급을 받았으면 이전 APICall 다시 호출
return await authApi(originalConfig)
} catch (_error) {
return Promise.reject(_error)
}
}
//Response 처리용
api.interceptors.response.use(
async (response) => {
switch (response.config.url) {
case '/todo':
await store.dispatch('setDatas', response.data)
break
}
return response
},
async (err) => {
// Do something with response error
const originalConfig = err.config
if (originalConfig.url !== '/auth/login' && err.response) {
if (err.response.status === 401 && !originalConfig._retry) {
return await reloadAccessToken(originalConfig)
}
}
console.log('TODO API Call 오류=>' + err)
return Promise.reject(err)
}
)
}
export default setup

View File

@ -1,6 +1,5 @@
import axios from 'axios'
const todoAPI = axios.create({
baseURL: process.env.VUE_APP_TODO_HOST,
headers: { 'Content-type': 'application/json' }
const todoApi = axios.create({
baseURL: process.env.VUE_APP_TODO_HOST
})
export default todoAPI
export default todoApi

View File

@ -27,6 +27,10 @@ localize('ko', ko)
Vue.component('ValidationObserver', ValidationObserver)
Vue.component('ValidationProvider', ValidationProvider)
//인터셉터 정의 및 Storage 연동
import interceptor from './interceptors/iterceptor'
interceptor()
Vue.config.productionTip = false
Vue.use(BootstrapVue)
new Vue({

View File

@ -1,7 +1,7 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import jwt from '../service/jwt'
import tokenService from '../service/token.service'
Vue.use(VueRouter)
const routes = [
@ -58,12 +58,13 @@ const router = new VueRouter({
// next : to에서 지정한 url로 이동하기 위해 꼭 호출해야 하는 함수
//여기에서 login은 path가 아니라 name에서 찾는다
//router.beforeEach()를 호출하고 나면 모든 라우팅이 대기 상태가 된다
router.beforeEach((to, from, next) => {
//1. routes 설정에서 meta: { requiredAuth: true } 가 선언된 경우
if (to.matched.some((route) => route.meta.requiredAuth)) {
//2. 로그인 체크용
const access_token = jwt.getAccessToken()
if (access_token === null && jwt.getRefreshToken() !== null) {
const access_token = tokenService.getLocalAccessToken()
if (access_token === null && tokenService.getLocalRefreshToken() !== null) {
//refreshToken은 있고 accessToken이 없을 경우 토큰 재발급 요청
this.$store.dispatch('refreshToken')
} else if (access_token) {

View File

@ -1,7 +1,36 @@
import api from '../interceptors/auth.api'
import tokenService from './token.service'
class AuthService {
async login(params) {
return await api.get('/auth/login', params)
async login(email, password) {
return await api
.post('/auth/login', { email: email, password: password })
.then((response) => {
const { data } = response
if (data.access_token) {
tokenService.setUser(data)
}
return data
})
}
logout() {
tokenService.removeUser()
}
async register({ email, password, name }) {
return api
.post('/auth/register', {
email,
password,
name
})
.then((response) => {
const { data } = response
if (data.access_token) {
tokenService.setUser(data)
}
return data
})
}
}
export default new AuthService()

View File

@ -1,43 +0,0 @@
import VueCookies from 'vue-cookies'
const getAccessToken = () => {
return VueCookies.get('access_token')
//return window.localStorage.getItem(key)
}
const getRefreshToken = () => {
return VueCookies.get('refresh_token')
//return window.localStorage.getItem(key)
}
const saveAccessToken = (access_token) => {
VueCookies.set('access_token', access_token.token, access_token.expireIn)
//window.localStorage.setItem(key, token)
}
const saveRefreshToken = (refresh_token) => {
VueCookies.set('refresh_token', refresh_token.token, refresh_token.expireIn)
//window.localStorage.setItem(key, token)
}
const destroyToken = () => {
VueCookies.remove('access_token')
VueCookies.remove('refresh_token')
//window.localStorage.removeItem(key)
}
const getAuthorizationHeader = (config) => {
//Request시 헤더에 로그인정보 추가하기 위함
if (getAccessToken()) {
//For Backend
config.headers.common['Authorization'] = 'Bearer ' + getAccessToken()
// for Node.js Express back-end
// config.headers["x-access-token"] = getAccessToken();
}
return config
}
export default {
getAccessToken,
getRefreshToken,
saveAccessToken,
saveRefreshToken,
destroyToken,
getAuthorizationHeader
}

View File

@ -1,7 +1,15 @@
import api from '../interceptors/todo.api'
import tokenService from './token.service'
class TodoService {
async setDatas(params) {
return await api.get('/todo', { params: params })
async login(params) {
console.log(params)
return await api.get('/todo', { params: params }).then((response) => {
const { data } = response
if (data.access_token) {
tokenService.setUser(data)
}
return data
})
}
}
export default new TodoService()

View File

@ -1,8 +1,4 @@
class TokenService {
getLocalRefreshToken() {
const user = JSON.parse(localStorage.getItem('user'))
return user?.refreshToken
}
getLocalAccessToken() {
const user = JSON.parse(localStorage.getItem('user'))
return user?.accessToken
@ -12,6 +8,10 @@ class TokenService {
user.accessToken = token
localStorage.setItem('user', JSON.stringify(user))
}
getLocalRefreshToken() {
const user = JSON.parse(localStorage.getItem('user'))
return user?.refreshToken
}
getUser() {
return JSON.parse(localStorage.getItem('user'))
}

View File

@ -1,4 +1,4 @@
import jwt from '../service/jwt'
import tokenService from '../service/token.service'
//참조: https://yamoo9.github.io/axios/guide/interceptors.html
// count state 속성 추가
@ -10,28 +10,24 @@ const getters = {
return state.takens
},
isAuthenticated: function () {
console.log('isAuthenticated:' + jwt.getAccessToken())
return !!jwt.getAccessToken()
const isAuthenticated =
!!tokenService.getLocalAccessToken() ||
!!tokenService.getLocalRefreshToken()
return isAuthenticated
}
}
const mutations = {
register: function (state, tokens) {
state.takens = tokens
jwt.saveAccessToken(tokens.access_token)
jwt.saveRefreshToken(tokens.refresh_token)
},
login: function (state, tokens) {
state.takens = tokens
jwt.saveAccessToken(tokens.access_token)
jwt.saveRefreshToken(tokens.refresh_token)
},
logout: function (state) {
state.takens = {}
jwt.destroyToken()
},
reload: function (state, access_token) {
state.takens.access_token = access_token
jwt.saveAccessToken(access_token)
}
}
const actions = {

View File

@ -5,12 +5,6 @@ import TodoStore from './todo.store'
Vue.use(Vuex)
//인터셉터 정의 및 Storage 연동
import setupAuthInterceptor from '../interceptors/auth.Iterceptor'
setupAuthInterceptor(AuthStore)
import setupTodoInterceptor from '../interceptors/todo.Iterceptor'
setupTodoInterceptor(TodoStore)
export default new Vuex.Store({
modules: {
AuthStore,