前端登录发起请求
1.安装axios
axios 是一个 HTTP 的网络请求库
安装 npm install axios (脚手架中)
在 main.js 中配置 axios
//导入网络请求库
import axios from 'axios';
//设置访问后台服务器地址:ip,端口和项目名字,请求时会自动和Login.vue中的this.$http.post("login")拼起来
axios.defaults.baseURL="http://127.0.0.1:8080/webBack/";
//将 axios 挂载到 vue 全局对象中,$http表示axios对象
Vue.prototype.$http=axios;
2.组装请求数据
提交更多的数据写在data的form(名字自定义的)中,form是个整体,提交给后端;表单中也要进行修改
将json对象序列化为键=值&键=值
<template>
<div class="login_container">
<!-- 登录盒子-->
<div class="login_box">
<!-- 头像盒子-->
<div class="img_box">
<img src="./assets/logo.png" />
</div>
<div style="margin-top: 100px; padding: 20px;">
<el-form ref="form" :model="form" label-width="80px"><!--:model="form"-->
<el-form-item label="账号">
<el-input v-model="form.account"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.password" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="login">登录</el-button>
<el-button class="el-icon-delete">取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
// 导出组件
export default{
data(){
return{
form:{
account:"",
password:""
}
}
},
methods:{
login(){//前端post向后端(这里的login为:后端LoginServlet的地址)发送post请求,然后回调(then)给前端 响应前端。接受到后端返回的数据,然后在执行以下内容
this.$http.post("login",jsonToString(this.form)).then((resp)=>{//$http表示axios对象
this.$router.push("/main");//前端进行路由跳转,this表示vue对象
})
}
},
mounted(){
}
}
//将json对象序列化为键=值&键=值
function jsonToString(jsonobj){
console.log(jsonobj)
var str = "";
for(var s in jsonobj){
str+=s+"="+jsonobj[s]+"&";
}
return str.substring(0,str.length-1);
}
</script>
<style>
.login_container{
height: 100vh;
margin: 0px;
padding: 0px;
background-image: url(assets/bg.jpg);
}
.login_box{
width: 450px;
height: 350px;
background-color: #fff;
border-radius: 10px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
opacity: 0.95;
}
.img_box{
width: 130px;
height: 130px;
position: absolute;
left: 50%;
transform: translate(-50%,-50%);
background-color: #fff;
border-radius: 50%;
padding: 5px;
border: 1px solid #eee;
}
.img_box img{
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #eee;
}
</style>
后端接收请求
package Servlet;
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("utf-8");//设置请求中数据解码的编码格式
String account=req.getParameter("account");
String password=req.getParameter("password");
System.out.println(account+"::"+password);
}
}
这时,在前端点击登录按钮之后,后端就会接收到 用户名::密码
连接数据库
1.创建web_db数据库和admin表
create database web_db charset utf8
create table admin(
id int primary key auto_increment,
account varchar(20) unique,
password varchar(20)
)
package model;
public class Admin {
private int id;
private String account;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
jdbc连接数据库
要返回admin,最好别返回true false,因为通过账号密码登录,查询显示用户其他更多的数据
package dao;
public class LoginDao {
public Admin login(String account, String password) throws ClassNotFoundException, SQLException {
Connection connection=null;
PreparedStatement ps=null;
Admin admin=null;//要返回admin,最好别返回true false,因为通过账号密码登录,然后显示别的更多的数据
try{
Class.forName("com.mysql.cj.jdbc.Driver");//动态加载Driver类
String url="jdbc:mysql://127.0.0.1:3306/web_db?serverTimezone=Asia/Shanghai";
String uname="root";
String psd="123456";
//出现的异常都抛出去 不处理,抛给LoginServlet,因为LoginServlet负责和用户进行交互
connection= DriverManager.getConnection(url,uname,psd);
ps=connection.prepareStatement("select id,account from admin where account=? and password=?");//登录是查询语句,有条件的进行查询
ps.setObject(1,account);
ps.setObject(2,password);
ResultSet rs=ps.executeQuery();
while(rs.next()){//查询有数据
admin = new Admin();
admin.setId(rs.getInt("id"));
admin.setAccount(rs.getString("account"));
}
}finally {
if(connection!=null){//connection==null时,本来就是关闭的状态
connection.close();
}
if(ps!=null){
ps.close();
}
}
return admin;
}
}
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("utf-8");//设置请求中数据解码的编码格式
String account=req.getParameter("account");
String password=req.getParameter("password");
//System.out.println(account+"::"+password);
try{
LoginDao loginDao=new LoginDao();
Admin admin=loginDao.login(account,password);//将前端接收到的值在数据库里查找,存到Admin
}catch (Exception e){
}
}
}
后端响应
1.接收到dao返回的查询数据
2.进行数据封装,创建了一个CommonResult类:code,data,message
3.进行逻辑判断
4.异常处理
package model;
//用来封装后端的数据
public class CommonResult {
private int code;//自定义的状态码
private Object data;//数据 对象 集合
private String message;//消息
public CommonResult(int code, Object data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public CommonResult(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package Servlet;
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("utf-8");//设置请求中数据解码的编码格式
//接收登录表单数据
String account=req.getParameter("account");
String password=req.getParameter("password");
resp.setContentType("text/html;charset=utf-8");//设置响应编码
PrintWriter printWriter= resp.getWriter();//拿到响应的输出流对象
CommonResult commonResult=null;//后端向前端响应的是CommonResult
try{
LoginDao loginDao=new LoginDao();
Admin admin=loginDao.login(account,password);//将前端接收到的值 数据库里,正常响应admin
if(admin!=null){
commonResult=new CommonResult(200,admin,"登录成功");
}else{
commonResult=new CommonResult(201,"账号或密码错误!");
}
}catch (Exception e){
e.printStackTrace();//打印异常信息
commonResult=new CommonResult(500,"系统忙");
}
ObjectMapper objectMapper=new ObjectMapper();
String json=objectMapper.writeValueAsString(commonResult);
printWriter.print(json);
}
}
可以在网络中的响应查看CommonResult的信息
前端处理
1.前端接收数据处理
2.前端路由跳转
methods:{
login(){
//预留与后端进行一次交互 account=admin&password=111
this.$http.post("login",jsonToString(this.form)).then((resp)=>{
if(resp.data.code==200){//resp.data是后端中的CommonResult
//提示
this.$message({message: resp.data.message,type: 'success'});
//路由跳转
this.$router.push("/main");
}
if(resp.data.code==201){
this.$message({message: resp.data.message,type: 'warning'});
}
if(resp.data.code==500){
this.$message.error(resp.data.message);
}
})
}
},
3.前端存储用户信息
sessionStorage,浏览器关闭之后会话就结束了,结束之后信息消失,下次登录之后重新存储信息
methods:{
login(){
//预留与后端进行一次交互 account=admin&password=111
this.$http.post("login",jsonToString(this.form)).then((resp)=>{
if(resp.data.code==200){
//提示
this.$message({message: resp.data.message,type: 'success'});
//在浏览器中存储用用户账号信息。resp.data是CommonResult
sessionStorage.setItem("account",resp.data.data.account);
//路由跳转
this.$router.push("/main");
}
if(resp.data.code==201){
this.$message({message: resp.data.message,type: 'warning'});
}
if(resp.data.code==500){
this.$message.error(resp.data.message);
}
})
}
},
4.在main组件中显示用户账号
data定义account
在声明周期函数里,拿到浏览器存储的account
然后挂载到页面上
<template>
<el-container>
<!-- 顶部-->
<el-header>
<div style="width: 500px; display: inline-block; font-size: 26px;font-weight: 400; color: #fff;">管理系统后台</div>
<el-dropdown style="float: right;">
<i class="el-icon-setting" style="margin-right: 15px">
<span>{{account}}</span>
</i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>修改密码</el-dropdown-item>
<el-dropdown-item>安全退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-container>
<!-- 左边-->
<el-aside width="200px">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>操作菜单</template>
<el-menu-item index="1-1">学生管理</el-menu-item>
<el-menu-item index="1-2">老师管理</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 工作区-->
<el-main>
Main
</el-main>
</el-container>
</el-container>
</template>
<script>
export default{
data(){
return{
account:""
}
},
methods:{
},
mounted() {
this.account=sessionStorage.getItem("account");
}
}
</script>
路由导航守卫
没有登录,不能直接访问非登录的页面
可以在Main.vue中进行判断,但是不建议。因为除了登录页面不需要进行判断,其他的页面都需要判断(要在每个组件中都判断),很麻烦
<script>
export default{
data(){
return{
account:""
}
},
methods:{
},
mounted() {
this.account=sessionStorage.getItem("account");
if(this.account==null){
this.$router.push("/login");
}
}
}
</script>
建议:在main.js 中判断
为路由对象,添加 beforeBach导航守卫
to-将要访问的页面地址,from-从哪个页面访问的,next-放行函数
//路由导航守卫,每次发生路由跳转时,就会自动的执行此段逻辑
rout.beforeEach((to, from, next) => {
if (to.path == '/login') {//如果用户访问的登录页, 直接放行
return next();//放行, 去to.path
} else {
var account = window.sessionStorage.getItem("account");//从浏览器中取出用户信息
if (account == null) {//表示没有登录
return next("/login");
} else {//已经登陆
next();
}
}
})
web会话跟踪
从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。
为什么要会话跟踪?
http是无状态的,登录完成后,客户端就与服务器断开了连接之后再向后端发送请求,后端就不知道是哪个客户端发送的,会话进行跟踪就是为了解决这样的问题。
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话过程。给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份
token
token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后, 服务器生成一个token便将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可。token保存在客户端,并且进行了加密,保证了数据的安全性。
目的:token的目的是为了减轻服务器的压力,使服务器更加健壮。
JWT
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一 种基于 JSON 的开放标准(RFC 7519)。定义了一种简洁的,自包含的方法用于通信双方之间以JSON 对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT 可以使用 HMAC 算法或者是 RSA 的公私秘钥对进行签名。
基于 token 的鉴权机制
基于 token 的鉴权机制类似于 http 协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于 token 认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
JWT 的主要应用场景
身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录中比较广泛的使用了该技术。信息交换在通信的双方之间使用 JWT 对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。
优点
1.简洁(Compact): 可以通过 URL,POST 参数或者在 HTTP header 发送,因为数据量小,传输速度也很快
2.自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
3.因为 Token 是以 JSON 加密的形式保存在客户端的,所以 JWT 是跨语言的,原则上任何 web 形式都支持。
4.不需要在服务端保存会话信息,特别适用于分布式微服务。
JWT 的构成
JWT 是由三段信息构成的,将这三段信息文本用.链接一起就构成了 Jwt 字符串。
就像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 用户的信息),第三部分是签证(signature).
🌈第一部分 header
jwt 的头部承载两部分信息:
声明类型,这里是 jwt
声明加密的算法 通常直接使用 HMAC HS256
完整的头部就像下面这样的 JSON:
{
'typ': 'JWT',
'alg': 'HS256'
}
然后将头部进行 base64 转码,构成了第一部分.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
🌈第二部分 playload
载荷就是存放有效信息的地方。这些有效 信息包含三个部分
标准中注册的声明
公共的声明。公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息(例如密码),因为该部分在客户端可解密. id,用户名,头像名
私有的声明
定义一个 payload
{
"sub": "1234567890","name": "John Doe",
"admin": true
}
然后将其进行 base64 转码,得到 Jwt 的第二部分。 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
🌈第三部分 signature
jwt 的第三部分是一个签证信息,这个签证信息由三部分组成:
header (base64 后的)
payload (base64 后的)
secret
这个部分需要 base64 转码后的 header 和 base64 转码后的 payload 使用.连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后就构成了 jwt 的第三部分。TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
base64是什么:64个基础编码字符,以六个比特位算出来对应的编号,去编码表找对应的字符
使用会话跟踪:
1.登录 向后端发送账号和密码
2.后端与数据库连接验证账号密码
3.如果账号密码正确,在后端生成一个token(令牌 唯一的),把token响应给前端
lib中添加
java-jwt-3.8.2.jar
commons-codec-1.15.jar
在util中写JWTUtil
package util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import model.Admin;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
//JWT工具类
public class JWTUtil {
//根据用户id,账号生成token
public static String getToken(Admin admin) {
String token = "";
try {
//过期时间 为1970.1.1 0:0:0 至 过期时间 当前的毫秒值 + 有效时间
Date expireDate = new Date(new Date().getTime() + 3600*1000);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
//设置头部信息
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
//携带id,账号信息,生成签名
token = JWT.create()
.withHeader(header)
.withClaim("id",admin.getId())
.withClaim("account",admin.getAccount())
.withExpiresAt(expireDate)
.sign(algorithm);
}catch (Exception e){
e.printStackTrace();
return null;
}
return token;
}
//验证token是否有效
public static boolean verify(String token){
try {
//验签
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {//当传过来的token如果有问题,抛出异常
return false;
}
}
//获得token 中playload部分数据,按需使用
public static DecodedJWT getTokenInfo(String token){
return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
}
}
将生成的token存到admin,然后响应给前端
package Servlet;
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("utf-8");//设置请求中数据解码的编码格式
//接收登录表单数据
String account=req.getParameter("account");
String password=req.getParameter("password");
resp.setContentType("text/html;charset=utf-8");//设置响应编码
PrintWriter printWriter= resp.getWriter();//拿到响应的输出流对象
CommonResult commonResult=null;//后端向前端响应的是CommonResult
System.out.println(account+"::"+password);
try{
LoginDao loginDao=new LoginDao();
Admin admin=loginDao.login(account,password);//将前端接收到的值 数据库里,正常响应admin
if(admin!=null){
//生成token
String token=JWTUtil.getToken(admin);
admin.setToken(token);
commonResult=new CommonResult(200,admin,"登录成功");
}else{
commonResult=new CommonResult(201,"账号或密码错误!");
}
}catch (Exception e){
e.printStackTrace();//打印异常信息
commonResult=new CommonResult(500,"系统忙");
}
ObjectMapper objectMapper=new ObjectMapper();
String json=objectMapper.writeValueAsString(commonResult);
printWriter.print(json);
}
}
package model;
public class Admin {
private int id;
private String account;
private String password;
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
4.在前端存储token
methods:{
login(){
//预留与后端进行一次交互 account=admin&password=111
this.$http.post("login",jsonToString(this.form)).then((resp)=>{
if(resp.data.code==200){
//提示
this.$message({message: resp.data.message,type: 'success'});
//在浏览器中存储用户账号信息
sessionStorage.setItem("account",resp.data.data.account);
sessionStorage.setItem("adminToken",resp.data.data.token)
//路由跳转
this.$router.push("/main");
}
if(resp.data.code==201){
this.$message({message: resp.data.message,type: 'warning'});
}
if(resp.data.code==500){
this.$message.error(resp.data.message);
}
})
}
},
5.之后的每次请求,都将token携带着向后端发送
Main.vue,向后端再次发送一个get请求
<script>
export default{
data(){
return{
account:""
}
},
methods:{
test(){
this.$http.get("back/test").then((resp)=>{
if(resp.data.code==200){
}
});
}
},
mounted() {
this.account = sessionStorage.getItem("account");
}
}
</script>
请求拦截,在main.js中,这样就不需要每次请求时添加Token
//axios ,请求拦截,每发送一次http请求,都会执行此拦截器
axios.interceptors.request.use(config =>{
//为请求头对象,添加 Token 验证的 token 字段
config.headers.adminToken = window.sessionStorage.getItem('adminToken');
return config;
})
请求成功之后,后端控制台打印:请求成功
package Servlet;public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求成功");
}
}
6.后端的java对请求中的token进行解析验证
后将此token每次与后端交互时,都放在请求头中
后端接收到token后,会对token进行验证是否符合规则,符合继续执行,不符合直接响应验在后端进行生产token,在后端验证token能够保证安全性
package filter;
public class AdminTokenFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("token验证过滤器");
//接收请求头中的adminToken
//将ServletRequest向下转为HttpServletRequest
HttpServletRequest request=(HttpServletRequest)servletRequest;
String adminToken = request.getHeader("adminToken");
boolean verify = JWTUtil.verify(adminToken);//验证token是否有效
if(verify){
filterChain.doFilter(servletRequest,servletResponse);//继续向后执行
}else{//token验证失败
servletResponse.setContentType("text/html;charset=utf-8");//设置响应编码
PrintWriter printWriter= servletResponse.getWriter();//拿到响应的输出流对象
CommonResult commonResult=new CommonResult(401,"token验证失败,请重新登陆");
ObjectMapper objectMapper=new ObjectMapper();
String json=objectMapper.writeValueAsString(commonResult);
printWriter.print(json);
}
}
}
<!--除了登录以外的请求地址,都加一个统一的前缀。就和登录的地址区分开-->
<filter>
<filter-name>adminTokenFilter</filter-name>
<filter-class>filter.AdminTokenFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>adminTokenFilter</filter-name>
<url-pattern>/back/*</url-pattern>
</filter-mapping>
7.在前端添加响应拦截器
main.js中,添加响应拦截器。可以将后端500,202 (token验证失败) 这些统一的状态码,进行拦截,减少了代码重复
// 添加响应拦截器
axios.interceptors.response.use((resp) => { //正常响应拦截
if (resp.data.code == 500) {
ElementUI.Message({
message: resp.data.message,
type: "error"
})
}
if (resp.data.code == 401) {
sessionStorage.clear();//token独证失败,认为登录失效,也可以清空前端存储的信息,重新让其登录
router.replace("/login");
}
return resp;
});
如果token不对,会被响应拦截器拦截,返回登录页面
安全退出
<template>
<el-container>
<!-- 顶部-->
<el-header>
<div style="width: 500px; display: inline-block; font-size: 26px;font-weight: 400; color: #fff;">
管理系统后台
</div>
<el-dropdown style="float: right;">
<i class="el-icon-setting" style="margin-right: 15px">
<span>{{account}}</span>
</i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>修改密码</el-dropdown-item>
<el-dropdown-item><span @click="logOut()">安全退出</span></el-dropdown-item>
<el-dropdown-item><span @click="test()">测试</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-container>
<!-- 左边-->
<el-aside width="200px">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>操作菜单</template>
<el-menu-item index="1-1">学生管理</el-menu-item>
<el-menu-item index="1-2">老师管理</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 工作区-->
<el-main>
Main
</el-main>
</el-container>
</el-container>
</template>
<script>
export default{
data(){
return{
account:""
}
},
methods:{
logOut(){
this.$confirm('您确定要退出吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
sessionStorage.clear();//清除浏览器中存储的用户信息
this.$router.push("/login");
})
},
test(){
this.$http.get("back/test").then((resp)=>{
if(resp.data.code==200){
}
});
}
},
mounted() {
this.account = sessionStorage.getItem("account");
}
}
</script>