vue2_frontend...
This commit is contained in:
parent
22543d0f15
commit
8da393dd29
@ -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) {
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
70
src/interceptors/iterceptor.js
Normal file
70
src/interceptors/iterceptor.js
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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()
|
||||
|
||||
@ -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'))
|
||||
}
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user