前端实现登录认证
01. 前端发送登录数据
后端写好了登录认证的接口之后,我们就可以将之与前端的代码结合起来了。
首先,在登陆组件中找到【登陆】按钮,绑定点击事件,调用登录处理方法loginHandle。
将前端数据发往后端进行验证。
在api中请求后端,api/user.js,代码:
import http from "../utils/http"
import {reactive, ref} from "vue"
const user = reactive({
login_type: 0, // 登录方式,0,密码登录,1,短信登录
account: "", // 登录账号/手机号/邮箱
password: "", // 登录密码
remember: false, // 是否记住登录状态
mobile: "", // 登录手机号码
code: "", // 短信验证码
login(){
// 用户登录
return http.post("/users/login/", {
"username": this.account,
"password": this.password,
})
}
})
export default user;
components/Login.vue
<template>
<div class="title">
<span :class="{active:user.login_type==0}" @click="user.login_type=0">密码登录</span>
<span :class="{active:user.login_type==1}" @click="user.login_type=1">短信登录</span>
</div>
<div class="inp" v-if="user.login_type==0">
<input v-model="user.account" type="text" placeholder="用户名 / 手机号码" class="user">
<input v-model="user.password" type="password" class="pwd" placeholder="密码">
<div id="geetest1"></div>
<div class="rember">
<label>
<input type="checkbox" class="no" v-model="user.remember"/>
<span>记住密码</span>
</label>
<p>忘记密码</p>
</div>
<button class="login_btn" @click="loginhandler">登录</button>
<p class="go_login" >没有账号 <span>立即注册</span></p>
</div>
<div class="inp" v-show="user.login_type==1">
<input v-model="user.mobile" type="text" placeholder="手机号码" class="user">
<input v-model="user.code" type="text" class="code" placeholder="短信验证码">
<el-button id="get_code" type="primary">获取验证码</el-button>
<button class="login_btn">登录</button>
<p class="go_login" >没有账号 <span>立即注册</span></p>
</div>
</template>
<script setup>
import user from "../api/user";
import { ElMessage } from 'element-plus'
// 登录处理
const loginHandler = ()=>{
// 验证数据
if(user.account.length<1 || user.password.length<1){
// 错误提示
console.log("错了哦,用户名或密码不能为空!");
ElMessage.error("错了哦,用户名或密码不能为空!");
return ;
}
// 登录请求处理
user.login().then(response=>{
console.log(response.data);
ElMessage.success("登录成功!");
}).catch(error=>{
ElMessage.error("登录失败!");
})
}
</script>
前面引用了 ElMessage
,为了让前端实现页面效果,需要引入对应的css文件。
src/main.js,代码:
import { createApp } from 'vue'
import App from './App.vue'
import 'element-plus/dist/index.css';
import router from "./router/index.js";
createApp(App).use(router).mount('#app')
02. 登录成功后保存jwt
我们可以将数据保存在浏览器的HTML5提供的本地存储对象中。
浏览器的本地存储提供了2个全局的js对象,给我们用于保存数据的,分别是sessionStorage 和 localStorage :
- sessionStorage 会话存储,浏览器关闭即数据丢失。
- localStorage 永久存储,长期有效,浏览器关闭了也不会丢失。
我们可以通过浏览器提供的Application调试选项中的界面查看到保存在本地存储的数据。
不同的域名或IP下的数据,互不干扰的,相互独立,也调用或访问不了其他域名下的数据。
sessionStorage和localStorage提供的操作一模一样,基本使用:
// 添加/修改数据
sessionStorage.setItem("变量名","变量值")
// 简写:sessionStorage.变量名 = 变量值
// 读取数据
sessionStorage.getItem("变量名")
// 简写:sessionStorage.变量名
// 删除一条数据
sessionStorage.removeItem("变量名")
// 清空所有数据
sessionStorage.clear() // 慎用,会清空当前域名下所有的存储在本地的数据
// 添加/修改数据
localStorage.setItem("变量名","变量值")
// 简写:localStorage.变量名 = 变量值
// 读取数据
localStorage.getItem("变量名")
// 简写:localStorage.变量名
// 删除数据
localStorage.removeItem("变量名")
// 清空数据
localStorage.clear() // 慎用,会清空当前域名下所有的存储在本地的数据
登陆子组件,components/Login.vue,代码:
<script setup>
import user from "../api/user";
import { ElMessage } from 'element-plus'
// 登录处理
const loginHandler = ()=>{
if(user.account.length<1 || user.password.length<1){
// 错误提示
console.log("错了哦,用户名或密码不能为空!");
ElMessage.error('错了哦,用户名或密码不能为空!');
return; // 在函数/方法中,可以阻止代码继续往下执行
}
// 发送请求
user.login({
username: user.account,
password: user.password
}).then(response=>{
// 保存token,并根据用户的选择,是否记住密码
localStorage.removeItem("token");
sessionStorage.removeItem("token");
console.log(response.data.token);
if(user.remember){ // 判断是否记住登录状态
// 记住登录
localStorage.token = response.data.token
}else{
// 不记住登录,关闭浏览器以后就删除状态
sessionStorage.token = response.data.token;
}
// 保存token,并根据用户的选择,是否记住密码
// 成功提示
ElMessage.success("登录成功!");
console.log("登录成功!");
// 关闭登录弹窗
}).catch(error=>{
console.log(error);
})
}
</script>
03. 登录成功后跳转页面
在components/Login.vue中,基于emit发送自定义事件通知父组件关闭当前登录窗口。
components/Login.vue:
<script setup>
import user from "../api/user"
import { ElMessage } from 'element-plus'
const emit = defineEmits(["successhandle",])
const loginHandler = ()=>{
// 登录处理
if(user.account.length<1 || user.password.length<1){
// 错误提示
ElMessage.error('错了哦,用户名或密码不能为空!');
return false // 在函数/方法中,可以阻止代码继续往下执行
}
// 发送请求
user.login({
username: user.username,
password: user.password
}).then(response=>{
// 保存token,并根据用户的选择,是否记住密码
localStorage.removeItem("token")
sessionStorage.removeItem("token")
if(user.remember){ // 判断是否记住登录状态
// 记住登录
localStorage.token = response.data.token
}else{
// 不记住登录,关闭浏览器以后就删除状态
sessionStorage.token = response.data.token
}
// 保存token,并根据用户的选择,是否记住密码
// 成功提示
ElMessage.success("登录成功!")
// 关闭登录弹窗,对外发送一个登录成功的信息
user.account = ""
user.password = ""
user.mobile = ""
user.code = ""
user.remember = false
emit("successhandle")
}).catch(error=>{
ElMessage.error("登录异常!")
})
}
</script>
在首页中是通过Header子组件调用的component/Login.vue,
所以我们需要在Header子组件中监听自定义事件login_success并关闭登陆弹窗即可。
components/Header.vue,代码:
<el-dialog :width="600" v-model="state.show_login">
<Login @successhandle="login_success"></Login>
</el-dialog>
<script setup>
import Login from "./Login.vue"
import nav from "../api/nav"
import {reactive} from "vue";
const state = reactive({
show_login: false,
})
nav.get_header_nav().then(response=>{
nav.header_nav_list = response.data;
})
// 用户登录成功以后的处理
const login_success = (token)=>{
state.show_login = false
}
</script>
views/Login.vue登陆页面中,登陆成功后直接路由跳转到首页即可。
views/Login.vue
,代码:
<template>
<div class="login box">
<img src="../assets/Loginbg.3377d0c.jpg" alt="">
<div class="login">
<div class="login-title">
<img src="../assets/logo.png" alt="">
<p>帮助有志向的年轻人通过努力学习获得体面的工作和生活!</p>
</div>
<div class="login_box">
<Login @successhandle="login_success"></Login>
</div>
</div>
</div>
</template>
<script setup>
import Login from "../components/Login.vue"
import router from "../router";
// 用户登录成功以后的处理
const login_success = ()=>{
// 跳转到首页
router.push("/");
}
</script>