在我的应用程序中,只有经过身份验证的用户才能访问某些路由。
当未经身份验证的用户点击必须登录的链接时,他将被重定向到登录组件。
如果用户成功登录,我想将他重定向到他必须登录之前请求的网址。但是,也应该有默认路由,以防用户在登录前没有请求其他URL。
如何使用vue-router实现此目的?
router.beforeEach(
(to, from, next) => {
if(to.matched.some(record => record.meta.forVisitors)) {
next()
} else if(to.matched.some(record => record.meta.forAuth)) {
if(!Vue.auth.isAuthenticated()) {
next({
path: '/login'
// Redirect to original path if specified
})
} else {
next()
}
} else {
next()
}
}
)
我的登录组件中的登录功能
login() {
var data = {
client_id: 2,
client_secret: '**************',
grant_type: 'password',
username: this.email,
password: this.password
}
// send data
this.$http.post('oauth/token', data)
.then(response => {
// authenticate the user
this.$auth.setToken(response.body.access_token,
response.body.expires_in + Date.now())
// redirect to route after successful login
this.$router.push('/')
})
我会非常感谢任何帮助!
答案 0 :(得分:22)
以一种不同的方式,这可以通过在您想要重定向时在路由中添加查询参数来实现,然后在设置参数时检查您何时登录;如果已设置,则使用它或以其他方式回溯根目录。
在代码中应该看起来像这样:
对您的链接执行操作,例如:
onLinkClicked() {
if(!isAuthenticated) {
// If not authenticated, add a path where to redirect after login.
this.$router.push({ name: 'login', query: { redirect: '/path' } });
}
}
登录提交操作
submitForm() {
AuthService.login(this.credentials)
.then(() => this.$router.push(this.$route.query.redirect || '/'))
.catch(error => { /*handle errors*/ })
}
希望它有所帮助。
答案 1 :(得分:6)
我知道这很旧,但这是google的第一个结果,对于那些只希望将其提供给您的人来说,这就是您添加到两个文件中的结果。就我而言,我正在使用Firebase进行身份验证。
这里的关键行是<?php
$arr[0][]=array('2018-06-13'=>"hadir");
$arr[0][]=array('2018-06-12'=>"hadir");
$arr[0][]=array('2018-06-11'=>"alfa");
$arr[1][]=array('2018-06-13'=>"hadir");
$arr[1][]=array('2018-06-12'=>"hadir");
$arr[1][]=array('2018-06-11'=>"hadir");
print_r($arr);
for($i=0;$i<count($arr);$i++){
for($j=0;$j<count($arr[$i]);$j++){
foreach($arr[$i][$j] as $k=>$v){
$newarr[$i][$k]=$v;
}
}
}
print_r($newarr);
?>
,在这里我得到他们第一次访问的相对路径,然后在查询中通过下一行const loginpath = window.location.pathname;
作为重定向中的查询。
next({ name: 'Login', query: { from: loginpath } });
这没什么好奇怪的,您会在对用户进行身份验证router.beforeEach((to, from, next) => {
const currentUser = firebase.auth().currentUser;
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
if (requiresAuth && !currentUser) {
const loginpath = window.location.pathname;
next({ name: 'Login', query: { from: loginpath } });
} else if (!requiresAuth && currentUser) next('menu');
else next();
});
时注意到我的操作,它将其发送到我们之前生成的查询网址。
this.$router.replace(this.$route.query.from);
我将更详细地阐述这种逻辑,但它仍然可以正常工作。希望这对访问该页面的人有所帮助。
答案 2 :(得分:2)
根据Matt C的回答,这可能是最简单的解决方案,但是那篇文章有一些问题,所以我认为最好写一个完整的解决方案。
目标路由可以存储在浏览器的会话存储中,并在身份验证后进行检索。在这种情况下,使用会话存储而不是使用本地存储的好处是,在结束浏览会话后数据不会保留。
在路由器的beforeEach钩子中,将会话路径设置为会话存储中的目标路径,以便在身份验证后可以对其进行检索。如果您是通过第三方身份验证提供程序(Google,Facebook等)重定向的,则此方法也适用。
router.js
//如果用户未通过身份验证,则在重定向以登录到beforeEach
之前sessionStorage.setItem('redirectPath', to.path)
因此,更完整的示例可能看起来像这样。我在这里使用Firebase,但如果您不是,则可以根据需要进行修改:
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(x => x.meta.requiresAuth);
const currentUser = firebase.auth().currentUser;
if (requiresAuth && !currentUser) {
sessionStorage.setItem('redirectPath', to.path);
next('/login');
} else if (requiresAuth && currentUser) {
next();
} else {
next();
}
});
login.vue
在登录方法中,经过身份验证后,您将获得一行代码,该代码会将用户发送到其他路由。现在,此行将从会话存储中读取值。然后,我们将从会话存储中删除该项目,以便将来不会意外使用该项目(例如,如果用户直接转到下一个身份验证的登录页面)。
this.$router.push(sessionStorage.getItem('redirectPath') || '/defaultpath');
sessionStorage.removeItem('redirectPath');
一个更完整的示例可能看起来像这样:
export default Vue.extend({
name: 'Login',
data() {
return {
loginForm: {
email: '',
password: ''
}
}
},
methods: {
login() {
auth.signInWithEmailAndPassword(this.loginForm.email, this.loginForm.password).then(user => {
//Go to '/defaultpath' if no redirectPath value is set
this.$router.push(sessionStorage.getItem('redirectPath') || '/defaultpath');
//Cleanup redirectPath
sessionStorage.removeItem('redirectPath');
}).catch(err => {
console.log(err);
});
},
},
});
答案 3 :(得分:1)
另一个快捷而肮脏的选择是使用本地存储,如下所示:
在您的beforeEach中,在重定向到登录之前,请放置以下代码行,以将初始请求的路径保存到本地存储中:
router.js
//如果用户未通过身份验证,则在重定向到登录名之前
localStorage.setItem('pathToLoadAfterLogin', from.path)
然后在登录组件中,成功登录后,可以重定向到先前创建的localStorage变量:
login.vue
// 如果用户登录成功,请将其路由到他们先前请求的内容或某些默认路由
this.$router.push(localStorage.getItem('pathToLoadAfterLogin') || 'somedefaultroute');
答案 4 :(得分:1)
如果按以下步骤设置了路由保护器
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!loggedIn) {
next({
path: "/login",
query: { redirect: to.fullPath }
});
} else {
next();
}
} else {
next();
}
});
可以在成功登录后提取并使用重定向查询
let searchParams = new URLSearchParams(window.location.search);
if (searchParams.has("redirect")) {
this.$router.push({ path: `${searchParams.get("redirect")}` });
} else this.$router.push({ path: "/dashboard" });
答案 5 :(得分:0)
Much easier with this library 和登录功能是
let redirect = this.$auth.redirect();
this.$auth
.login({
data: this.model,
rememberMe: true,
redirect: { name: redirect ? redirect.from.name : "homepage", query: redirect.from.query },
fetchUser: true
})
答案 6 :(得分:0)
这将帮助您@Schwesi。
Router.beforeEach(
(to, from, next) => {
if (to.matched.some(record => record.meta.forVisitors)) {
if (Vue.auth.isAuthenticated()) {
next({
path: '/feed'
})
} else
next()
}
else if (to.matched.some(record => record.meta.forAuth)) {
if (!Vue.auth.isAuthenticated()) {
next({
path: '/login'
})
} else
next()
} else
next()
}
);
答案 7 :(得分:0)
这对我有用。
this.axios.post('your api link', {
token: this.token,
})
.then(() => this.$router.push(this.$route.query.redirect || '/dashboard'))