Vuejs2 如果用户';它已经被认证了?
说明 我用Vuejs2 如果用户';它已经被认证了?,vuejs2,vue-component,vue-router,vuetify.js,auth0,Vuejs2,Vue Component,Vue Router,Vuetify.js,Auth0,说明 我用vue.js构建了一个非常标准的SPA,在这里我使用Auth0通过下面的示例来处理身份验证部分。应用程序流程如下所示: 通过Auth0锁在Initial.vue中注册->回调被调用->用户重定向到/home 上述流程中的所有内容都可以正常工作,但问题在于: 问题 一旦用户注册并在/home中,我希望他能够访问所有其他路径(例如/doctors),如果未通过身份验证,则应提示他再次登录。根据上述链接,这在路由器中处理。在每个功能之前 访问/登录页面(Initialvue)时出现我的问题。
vue.js
构建了一个非常标准的SPA
,在这里我使用Auth0
通过下面的示例来处理身份验证部分。应用程序流程如下所示:
通过Auth0锁在Initial.vue中注册
->回调被调用
->用户重定向到/home
上述流程中的所有内容都可以正常工作,但问题在于:
问题
一旦用户注册并在/home
中,我希望他能够访问所有其他路径(例如/doctors
),如果未通过身份验证,则应提示他再次登录。根据上述链接,这在路由器中处理。在每个功能之前
访问/
登录页面(Initialvue
)时出现我的问题。当用户已经注册并试图访问该路由时,我希望他被重定向到/home
并跳过登录
页面。我曾尝试使用beforenter
路由实现此功能,但auth.isAuthenticated
失败,原因是tokenexpiration
为空(即使用户已通过身份验证
代码
我的AuthService.js
:
import auth0 from 'auth0-js';
import EventEmitter from 'events';
import authConfig from '../config/auth_config.json';
const webAuth = new auth0.WebAuth({
domain: authConfig.domain,
redirectUri: `${window.location.origin}/callback`,
clientID: authConfig.clientId,
responseType: 'id_token',
scope: 'openid profile email'
});
const localStorageKey = 'loggedIn';
const loginEvent = 'loginEvent';
class AuthService extends EventEmitter {
idToken = null;
profile = null;
tokenExpiry = null;
// Starts the user login flow
login(customState) {
webAuth.authorize({
appState: customState
});
}
// Handles the callback request from Auth0
handleAuthentication() {
return new Promise((resolve, reject) => {
webAuth.parseHash((err, authResult) => {
if (err) {
reject(err);
} else {
this.localLogin(authResult);
resolve(authResult.idToken);
}
});
});
}
localLogin(authResult) {
// console.log(authResult); TODO-me: Handle this
this.idToken = authResult.idToken;
this.profile = authResult.idTokenPayload;
// Convert the JWT expiry time from seconds to milliseconds
this.tokenExpiry = new Date(this.profile.exp * 1000);
localStorage.setItem(localStorageKey, 'true');
this.emit(loginEvent, {
loggedIn: true,
profile: authResult.idTokenPayload,
state: authResult.appState || {}
});
}
renewTokens() {
return new Promise((resolve, reject) => {
if (localStorage.getItem(localStorageKey) !== "true") {
return reject("Not logged in");
}``;
webAuth.checkSession({}, (err, authResult) => {
if (err) {
reject(err);
} else {
this.localLogin(authResult);
resolve(authResult);
}
});
});
}
logOut() {
localStorage.removeItem(localStorageKey);
this.idToken = null;
this.tokenExpiry = null;
this.profile = null;
webAuth.logout({
returnTo: window.location.origin
});
this.emit(loginEvent, { loggedIn: false });
}
isAuthenticated() {
console.log('In tokenExp is:');
console.log(this.tokenExpiry); //THIS returns null when /home -> /
return (
Date.now() < this.tokenExpiry &&
localStorage.getItem(localStorageKey) === 'true'
);
}
}
export default new AuthService();
import Vue from 'vue';
import Router from 'vue-router';
import auth from '../auth/AuthService';
import Callback from '../components/Callback';
Vue.use(Router)
// export default new Router({
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
// {
// path: '/',
// name: 'login',
// component: () => import('@/views/Login')
// },
{
path: '/',
name: 'initial',
component: () => import('@/views/Initial'),
// meta: {isAuth: true},
beforeEnter: ((to, from, next) => {
// if (to.matched.some(record => record.meta.isAuth)) {
console.log(auth.isAuthenticated()); //THIS is false for the above scenario
if (auth.isAuthenticated()) {
next({
path: '/home',
query: {redirect: to.fullPath}
})
} else {
next()
}
// }
})
},
{
path: '/callback',
name: 'callback',
component: Callback
},
{
path: '/home',
name: 'home',
component: () => import('@/views/Home')
},
{
path: '/doctors',
name: 'doctors',
component: () => import('@/views/Doctors')
},
{
path: '/complete-signup',
name: 'complete-signup',
component: () => import('@/views/CompleteSignup')
},
]
});
// Add a `beforeEach` handler to each route
router.beforeEach((to, from, next) => {
if (to.path === "/" || to.path === "/callback" || auth.isAuthenticated()) {
return next();
}
// Specify the current path as the customState parameter, meaning it
// will be returned to the application after auth
console.log('OUT beforeach if');
auth.login({ target: to.path });
});
我的回调.vue
:
<template>
<v-container
app
fluid
>
<v-parallax
src="https://cdn.vuetifyjs.com/images/backgrounds/vbanner.jpg"
height="1000"
>
<v-layout
row
wrap
>
<!-- LOGIN-->
<v-toolbar
flat
light
dense
color="transparent"
>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn
medium
color="lime lighten-2"
@click="login"
class="font-weight-bold title text-uppercase"
>
Login
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-layout
align-center
column
>
<h1 class="display-2 font-weight-thin mb-3 text-uppercase lime--text lighten-2" >Pulse</h1>
<h4 class="subheading">A digital intelligent insurance built for you!</h4>
</v-layout>
</v-layout>
</v-parallax>
</v-container>
</template>
<script>
import VContainer from "vuetify/lib/components/VGrid/VContainer";
import VFlex from "vuetify/lib/components/VGrid/VFlex";
import VLayout from "vuetify/lib/components/VGrid/VLayout";
import VBtn from "vuetify/lib/components/VBtn/VBtn";
import VToolbar from "vuetify/lib/components/VToolbar/VToolbar";
import VParallax from "vuetify/lib/components/VParallax/VParallax";
export default {
name: "Initial",
components: {
VContainer,
VLayout,
VFlex,
VBtn,
VToolbar,
VParallax
},
data() {
return {
isAuthenticated: false
};
},
async created() {
try {
await this.$auth.renewTokens();
} catch (e) {
// console.log(e);
}
},
methods: {
login() {
this.$auth.login();
},
// logout() {
// this.$auth.logOut();
// },
handleLoginEvent(data) {
this.isAuthenticated = data.loggedIn;
this.profile = data.profile;
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<p>Loading...</p>
</div>
</template>
<script>
export default {
methods: {
handleLoginEvent(data) {
console.log('State.target is:');
console.log(data.state.target);
//If user has just signed up redirect to complete-signup form
if ((data.profile['<AUTH_DOMAIN>'].justSignedUp) && (data.state.target===undefined)){
// this.$router.push(data.state.target || "/complete-signup");
this.$router.push('/complete-signup');
}else {
// this.$router.push('/home');
this.$router.push(data.state.target);
}
}
},
created() {
this.$auth.handleAuthentication();
}
}
</script>
<style scoped>
</style>
“CompleteSignup是我的注册表单,注册后用户填写表单,然后通过
axios发布,然后重定向到
/home`:
//Form data before
methods: {
this.$store.dispatch(REGISTER,registerFormData)
.then(() => this.$router.push('/home'));
}
我还使用了vuetify
,我的主要App.vue
组件是:
<template>
<v-app
style= "background: #E0EAFC; /* fallback for old browsers */
background: -webkit-linear-gradient(to left, #CFDEF3, #E0EAFC); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to left, #CFDEF3, #E0EAFC); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
"
>
<v-content>
<router-view></router-view>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
components: {
}
};
</script>
<style>
</style>
导出默认值{
名称:“应用程序”,
组成部分:{
}
};
您可以简化问题,将默认行为设置为用户登录的行为,然后使用route guard保护相应的路由
1) 将您的/
指向/home
2) 为登录创建单独的路由/“初始”
3) 使用beforeach
钩子确保用户经过身份验证,如果没有,则将其重定向到您的Initial.vue
(或直接触发auth.login()
)
我想出来了。问题在于this.tokenexpiration
,this.idToken
,this.profile
值将在回调
视图中分配一个值,该视图位于登录
之后,此外,这些值与我在mixin
中定义的特定Vue原型实例相关联。因此,当导航回初始页面时,此
未定义,因为它与特定的Vue实例没有关联。我也遇到过同样的情况(使用React),我将尝试解释如何解决它
首先,在身份验证中,需要在客户端存储令牌(可以使用localStorage/cookie)
您需要一个SecureComponent
,此组件将仅检查存储的令牌是否存在
FetchHandler
此组件处理每个受保护的应用程序
并将检查响应代码,如果是401(例如),则将用户重定向到身份验证组件。此步骤可以作为附加层添加到SecureComponent
您是否检查了localLogin
中的authResult
,并首先验证了tokenExpiry
设置是否正确?是。注册后,我可以在应用程序中导航,也可以在控制台中看到tokenExpiry有一个值;这将是一个解决办法。我会试试看。顺便说一下,进一步的调试表明,在这种情况下,所有this
值(例如idToken
,profile
,tokenexpiration
)都为空。这让我相信,当我试图访问这个
实例时,组件没有被渲染。
...
{
path: '/',
redirect: 'home'
},
{
path: '/initial',
...
...
}
...
router.beforeEach((to, from, next) => {
if(to.name == 'callback' || auth.isAuthenticated()) {
next()
} else { // trigger auth0 login or redirect to your Initial.vue
auth.login()
// next({ path: '/initial' })
}
})