Firebase 身份验证和 Vue 路由器 [英] Firebase Auth and Vue-router
问题描述
我正在尝试使用 firebase 验证 Vue.js 应用程序.
我有一个问题,如果在登录时尝试直接访问受登录保护的 URL,路由器将加载并检查 auth 状态,然后 firebase.js 有时间返回 auth 响应.这会导致用户被退回到登录页面(当他们已经登录时).
如何延迟 vue-router 导航,直到从 firebase 检索到 auth 状态?我可以看到 firebase 将身份验证数据存储在 localStorage 中,检查它是否存在作为初步身份验证检查是否安全?理想情况下,最终结果是在用户通过身份验证时显示加载微调器或其他内容,然后他们应该能够访问他们导航到的页面.
路由器/index.js
let router = new Router({模式:'历史',路线: [{小路: '/',name: '家',组件:首页},{路径:'/登录',name: '登录',组件:登录},{路径:'/示例',name: '例子',组件:示例,beforeEnter: loginRequired}})函数 loginRequired (to, from, next) {如果(authService.authenticated()){下一个()} 别的 {下一个('/登录')}}
auth.js
import * as firebase from 'firebase'变量配置 = {//火力配置}firebase.initializeApp(config)var authService = {火力基地:火力基地,用户:空,认证(){如果(this.user == null){返回假} 别的 {返回 !this.user.isAnonymous}},设置用户(用户){this.user = 用户},登录(电子邮件,密码){返回 this.firebase.auth().signInWithEmailAndPassword(email, password).then(用户 => {this.setUser(用户)})},登出 () {this.firebase.auth().signOut().then(() => {console.log('注销完成')})}}firebase.auth().onAuthStateChanged(user => {authService.setUser(用户)})导出默认 authService
app.vue
<div id="应用程序"><p v-if="auth.user !== null">使用{{ auth.user.email }}登录</p><p v-else>未登录</p><router-view v-if="auth.user !== null"></router-view>
模板><脚本>从 './auth' 导入 authService导出默认{名称:'应用',数据 () {返回 {身份验证:身份验证服务}}}
Firebase 总是在启动时触发 auth 状态更改事件,但不会立即触发.
您需要让 authService.authenticated
返回一个承诺,以等待 Firebase 完成其用户/身份验证初始化.
const initializeAuth = new Promise(resolve => {//这为初始 auth-change 事件添加了一个钩子firebase.auth().onAuthStateChanged(user => {authService.setUser(用户)解决(用户)})})const authService = {用户:空,认证(){返回 initializeAuth.then(用户 => {返回用户 &&!user.isAnonymous})},设置用户(用户){this.user = 用户},登录(电子邮件,密码){返回 firebase.auth().signInWithEmailAndPassword(email, password)},登出 () {firebase.auth().signOut().then(() => {console.log('注销完成')})}}
您不需要从 signInWith...
承诺中调用 setUser
,因为这已经由 initializeAuth
承诺处理.
I'm trying to authenticate a Vue.js app using firebase.
I have an issue where if trying to access a login-protected URL directly while logged in, the router will load and check for auth state before firebase.js has time to return the auth response. This results in the user being bounced to the login page (while they are already logged in).
How do I delay vue-router navigation until auth state has been retrieved from firebase? I can see that firebase stores the auth data in localStorage, would it be safe to check if that exists as a preliminary authentication check? Ideally the end result would be to show a loading spinner or something while the user is authenticated, then they should be able to access the page they navigated to.
router/index.js
let router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/example',
name: 'Example',
component: Example,
beforeEnter: loginRequired
}
})
function loginRequired (to, from, next) {
if (authService.authenticated()) {
next()
} else {
next('/login')
}
}
auth.js
import * as firebase from 'firebase'
var config = {
// firebase config
}
firebase.initializeApp(config)
var authService = {
firebase: firebase,
user: null,
authenticated () {
if (this.user == null) {
return false
} else {
return !this.user.isAnonymous
}
},
setUser (user) {
this.user = user
},
login (email, password) {
return this.firebase.auth().signInWithEmailAndPassword(email, password)
.then(user => {
this.setUser(user)
})
},
logout () {
this.firebase.auth().signOut().then(() => {
console.log('logout done')
})
}
}
firebase.auth().onAuthStateChanged(user => {
authService.setUser(user)
})
export default authService
app.vue
<template>
<div id="app">
<p v-if="auth.user !== null">Logged in with {{ auth.user.email }}</p>
<p v-else>not logged in</p>
<router-view v-if="auth.user !== null"></router-view>
</div>
</template>
<script>
import authService from './auth'
export default {
name: 'app',
data () {
return {
auth: authService
}
}
}
</script>
Firebase always triggers an auth state change event on startup but it's not immediate.
You'll need to make authService.authenticated
return a promise in order to wait for Firebase to complete its user/auth initialisation.
const initializeAuth = new Promise(resolve => {
// this adds a hook for the initial auth-change event
firebase.auth().onAuthStateChanged(user => {
authService.setUser(user)
resolve(user)
})
})
const authService = {
user: null,
authenticated () {
return initializeAuth.then(user => {
return user && !user.isAnonymous
})
},
setUser (user) {
this.user = user
},
login (email, password) {
return firebase.auth().signInWithEmailAndPassword(email, password)
},
logout () {
firebase.auth().signOut().then(() => {
console.log('logout done')
})
}
}
You don't need to call setUser
from the signInWith...
promise as this will already be handled by the initializeAuth
promise.
这篇关于Firebase 身份验证和 Vue 路由器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!