vuejs2 - 如果用户已经通过身份验证,使用 vue.js 和 Auth0 如何跳过登录页面?

标签 vuejs2 vue-component vue-router vuetify.js auth0

描述

我有一个非常标准的 SPA内置 vue.js我在哪里使用 Auth0按照 official 处理认证部分例子。应用流程如下:
Register in the Initial.vue via Auth0 lock -> Callback is called -> User's redirected to /home
上述流程中的所有内容都可以正常工作,但问题在于:

问题

一旦用户注册并在/home如果经过身份验证,我希望他能够访问所有其他路由(例如 /doctors ),如果没有,他应该提示他再次登录。根据上面的链接,这是在 router.beforeEach 中处理的功能。

访问/时出现我的问题登录页面 ( Initialvue )。当用户已经注册并尝试访问该路由时,我希望他被重定向到 /home并跳过 login页。我试过用 beforeEnter 来实现这个路线但auth.isAuthenticated由于 tokenExpiry 失败为空(即使用户已通过身份验证!

代码

我的 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();

我的 Initial.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>

我的 Callback.vue :
<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>

我的 router.js :
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 });
});

'CompleteSignup is my signup form after registering where the user's is filling out a form and then posting it via axios and then redirected to/家`:
//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>

最佳答案

您可以通过将默认行为设置为用户登录的行为来简化问题,然后使用路由保护器保护相应的路由。

1) 点你的 //home2)为登录/“初始”创建单独的路由
3) 使用 beforeEach Hook 以确保用户已通过身份验证,如果没有,则将他重定向到您的 Initial.vue (或直接触发 auth.login())

...
  {
    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' })
  }
})

关于vuejs2 - 如果用户已经通过身份验证,使用 vue.js 和 Auth0 如何跳过登录页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56088916/

相关文章:

javascript - 如何将多个文件转为base64字符串?

typescript - 类型 'x' 上不存在属性 'Vue'

arrays - vue v-if 无法访问数组中的 bool 值

vue.js - 如何解决Vue router change error with param?

javascript - Vue-Router 仅适用于某些路由

css - Vis Network + Vuetify Tabs - 网络不会填满屏幕

javascript - 我如何使用 VueFire 将 prop 作为 firebase 路径的一部分?

javascript - 当我使用 vue-router 时,我的组件的内容没有显示

vue-router - 在 vuetify.js 中,将路由器路径指定为属性(<v-btn to ="/path">)使按钮看起来像是处于 "hover"状态

typescript - Vue 和 TypeScript 需要 prop