firebase.js
Vue.prototype.$isFirebaseAuth = false;
onAuthStateChanged(auth, (user) => {
if (user) {
Vue.prototype.$isFirebaseAuth = true;
console.log("onAuthStateChanged ===>");
console.log(user);
router.push("/");
} else {
//로그인 인증 안된경우
Vue.prototype.$isFirebaseAuth = false;
router.push("/sign") ;
}
store.dispatch('getUser', user);
});
router/index.js
router.beforeEach((to, from, next) => {
//인증후 true 일경우에만 이동
console.log("브라우터 네비게이션 가드 - beforeEach ");
if (to.path != "/sign") { //로그인 페이지가 아닌 모든 경로
if (Vue.prototype.$isFirebaseAuth) next(); //인증이 된경우는 통과
return;
}
next();
})
소스 :https://github.com/braverokmc79/vf/commit/7a8a69e0bd7730c0c91dff27dfdae2b09e1c4b2c
로그인 : http://macaronics.net/index.php/m04/vue/view/1839
원리는
파이어베이스를 통해 로그인 후 파이어베이스에서 인증 정보 받아서 store 에 user, claims 저장 시킨다.
파이베이스 onAuthStateChanged( ) 함수는 실시간으로 를 통해 인증처리 정보를 감시하며 인증 처리되면 store 에 저장 시킨다.
네비게이션 가드 통해 페이지 이동전에 인증여부를 확인하고 레벨을 확인한다.
ex)
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import store from '../store'
Vue.use(VueRouter)
const adminCheck = (to, form, next) => {
console.log("adminCheck =>");
if (!store.state.user) {
if (to.path !== '/sign') return next("/sign");
next("/test/lv2"); //게스트 페이지
}
if (!store.state.user.emailVerified) return next("/userProfile");
if (store.state.claims.accessLevel <9) {
throw Error("관리자만 들어갈 수 있습니다.")
}
next();
}
const userCheck = (to, form, next) => {
console.log("userCheck");
if (!store.state.user) {
if (to.path !== '/sign') return next("/sign");
next("/test/lv2"); //게스트 페이지 이동
}
if (!store.state.user.emailVerified) return next("/userProfile");
next();
}
const guestCheck = (to, form, next) => {
console.log("guestCheck");
return next();
}
const routes = [
{
path: '/',
name: 'Home',
component: Home
}
, {
path: '/test/lv0',
name: 'lv0',
component: () => import('../views/test/lv0.vue'),
beforeEnter: adminCheck
}
, {
path: '/test/lv1',
name: 'lv1',
component: () => import('../views/test/lv1.vue'),
beforeEnter: userCheck
}
, {
path: '/test/lv2',
name: 'lv2',
component: () => import('../views/test/lv2.vue'),
beforeEnter: guestCheck
}
,
{
path: '/sign',
name: 'sing',
component: () => import('../views/sign.vue'),
beforeEnter: (to, from, next) => {
console.log("값 :" +store.state.claims);
if (store.state.user===null) return next();
next("/");
}
}
]
const router = new VueRouter(
{mode: 'history', base: process.env.BASE_URL, routes}
)
//stoer 에 파이어베이스 인증된 정보 값 user, clamis 값이 들어갈 때 까지 대기 구문
const waiteFirebase = () => {
return new Promise((resolve, reject) => {
let cnt = 0;
const tmr = setInterval(() => {
if (store.state.firebaseLoaded) {
clearInterval(tmr)
resolve();
} else if (cnt++ > 200) { //2초
clearInterval(tmr);
reject(Error('파이어베이스 로드가 안되었습니다.'));
}
})
}, 10);
}
router.beforeEach((to, from, next) => {
if (Vue.prototype.$isFirebaseAuth) next(); //인증이 된경우는 통과
waiteFirebase()
.then(() => next())
.catch(e => Vue.prototype.$toasted.global.error(e.message));
});
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => {
if (err.name !== 'NavigationDuplicated') throw err;
});
};
router.onError(e => {
console.log("라우터 에러 : " + e.message);
Vue.prototype.$toasted.global.error(e.message);
})
export default router
plugins/firebase.js
import "firebase/auth";
import "firebase/firestore";
import Vue from 'vue'
import * as firebase from 'firebase/app';
import { initializeApp } from 'firebase/app';
import { query, orderBy, startAfter, limit, endBefore, limitToLast } from "firebase/firestore";
import { getFirestore, collection, getDocs, serverTimestamp, addDoc, doc, getDoc, updateDoc, deleteDoc, setDoc } from 'firebase/firestore';
import firebaseConfig from '../../firebaseConfig.js';
import { head } from 'lodash'
import store from "../store/index.js";
//구글 로그인 인증
import {
signInWithPopup, GoogleAuthProvider, initializeAuth,
browserSessionPersistence, browserPopupRedirectResolver, createUserWithEmailAndPassword,
signInWithEmailAndPassword, onAuthStateChanged, signOut, updateProfile
//getAuth
} from "firebase/auth";
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = initializeAuth(app, {
persistence: browserSessionPersistence,
popupRedirectResolver: browserPopupRedirectResolver,
});
const provider = new GoogleAuthProvider();
//collectionName => table 이름
//1. 아이디 자동 생성 firebase 저장하기
async function fbWrite(collectionName, objData) {
//firebase 데이터 저장 - addDoc 일경우 아이디가 자동 생성
await addDoc(collection(getFirestore(), collectionName), objData);
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체등록 갯수 업데이트 // totNum.exists() 존재할 경우 업데이트 처리 - 카운트 증가처리 : 없으면 1 로 최초등록
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.exists() ? totNum.data().totalCount + 1 : 1,
upDate: serverTimestamp()
});
}
//아이디가 존재할 경우
async function fbWriteSetDoc(collectionName, id, objData) {
//firebase 데이터 저장 - setDoc 일경우 아이디가 자동 생성
await setDoc(doc(db, collectionName, id), objData);
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체등록 갯수 업데이트 // totNum.exists() 존재할 경우 업데이트 처리 - 카운트 증가처리 : 없으면 1 로 최초등록
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.exists() ? totNum.data().totalCount + 1 : 1,
upDate: serverTimestamp()
});
}
//firebase 삭제하기
async function fbDelete(collectionName, id) {
await deleteDoc(doc(db, collectionName, id));
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체 갯수 업데이트 // totNum.docs[0] 값이 없을 경우 최초 등록으로 1 , 존재할 경우 업데이트 처리 - 카운트 감소
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.data().totalCount > 0 ? totNum.data().totalCount - 1 : 0,
upDate: serverTimestamp()
});
}
//firebase 수정하기
async function fbUpdate(collectionName, objData) {
const updateData = doc(db, collectionName, objData.id);
await updateDoc(updateData, objData);
}
//firebase 한개의 데이터 가져오기
async function fbGetData(collectionName, id) {
const docRef = doc(db, collectionName, id);
return await getDoc(docRef);
}
// firebase 데이터 목록 가져오기
async function fbGetList(collectionName) {
const querySnapshot = await getDocs(collection(db, collectionName));
return querySnapshot;
}
// firebase query 데이터 목록 가져오기
async function fbGetQueryList(collectionName, culum, order, pageSize, documentSnapshots, currentPage, beforPage) {
//1. 첫 페이지일 경우
if (currentPage == undefined || currentPage == 1) {
//1.첫페이지일 경우
const first = query(collection(db, collectionName),
orderBy(culum, order),
limit(pageSize));
const documentSnapshots2 = await getDocs(first);
return documentSnapshots2;
}
if (beforPage <= currentPage) {
//2.next 다음 페이지로 이동
const lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1];
if (documentSnapshots.size == 0) {
return;
}
const next = query(collection(db, collectionName),
orderBy(culum, order),
startAfter(lastVisible),
limit(pageSize));
const documentSnapshots2 = await getDocs(next);
return documentSnapshots2;
} else {
//3.이전 페이지로 이동
const prevVisible = documentSnapshots.docs;
const before = query(collection(db, collectionName),
orderBy(culum, order),
endBefore(head(prevVisible)),
limitToLast(pageSize + 1)
);
const documentSnapshots2 = await getDocs(before);
return documentSnapshots2;
}
}
Vue.prototype.$isFirebaseAuth = false;
// onAuthStateChanged(auth, (user) => {
// if(user){
// Vue.prototype.$isFirebaseAuth = true;
// router.push("/");
// } else {
// Vue.prototype.$isFirebaseAuth = false;
// router.push("/sign");
// }
// store.dispatch('getUser', user)
// });
onAuthStateChanged(auth, (user) => {
console.log("onAuthStateChanged : =>");
store.dispatch('getUser', user);
});
//전역변수로 사용 설정
Vue.prototype.$firebase = firebase
Vue.prototype.$fbWrite = fbWrite
Vue.prototype.$fbWriteSetDoc = fbWriteSetDoc
Vue.prototype.$fbUpdate = fbUpdate
Vue.prototype.$fbGetList = fbGetList
Vue.prototype.$fbGetQueryList = fbGetQueryList
Vue.prototype.$fbDelete = fbDelete
Vue.prototype.$fbGetData = fbGetData
Vue.prototype.$db = db
Vue.prototype.$getFirestore = getFirestore
Vue.prototype.$collection = collection
Vue.prototype.$getDocs = getDocs
Vue.prototype.$serverTimestamp = serverTimestamp
Vue.prototype.$addDoc = addDoc
Vue.prototype.$doc = doc
Vue.prototype.$getDoc = getDoc
Vue.prototype.$updateDoc = updateDoc
Vue.prototype.$deleteDoc = deleteDoc
Vue.prototype.$signOut = signOut
Vue.prototype.$updateProfile = updateProfile
Vue.prototype.$onAuthStateChanged = onAuthStateChanged
Vue.prototype.$signInWithPopup = signInWithPopup
Vue.prototype.$GoogleAuthProvider = GoogleAuthProvider
Vue.prototype.$auth = auth
Vue.prototype.$provider = provider
Vue.prototype.$createUserWithEmailAndPassword = createUserWithEmailAndPassword
Vue.prototype.$signInWithEmailAndPassword = signInWithEmailAndPassword
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
title: '원래 제목',
user: null,
token: '',
loading: false,
claims: null,
firebaseLoaded: false,
dimLayer: true
},
mutations: {
setTitle(state, payload) {
state.title = payload;
},
setUser(state, payload) {
state.firebaseLoaded = true;
state.user = payload;
},
setToken(state, token) {
state.token = token;
},
setClaims(state, claims) {
state.claims = claims;
},
},
actions: {
async getUser({commit}, user){
commit('setUser', user);
if (!user) return;
const token = await user.getIdToken();
commit('setToken', token);
const resultToken = await user.getIdTokenResult();
commit('setClaims', resultToken.claims);
},
setClaims({commit}, claims) {
commit('setClaims', claims);
},
},
modules: {}
})
https://github.com/braverokmc79/vf/commit/4a44c612e88b53c4fc6a30a921f01de72b07033f
https://youtu.be/bxwhJKyYNnI?list=PLjpTKic1SLZs3GsJXwKgoJWu6wNQKt_GY















댓글 ( 4)
댓글 남기기