前后端分离项目之登录页面(前后端请求、响应和连接数据库)

news2024/11/29 4:49:29

目录

一、前端登录发起请求

二、后端请求接收

三、连接数据库

四、后端响应

五、前端处理

六、在前端验证用户是否登录

七、web会话跟踪

八、请求拦截器和响应拦截器


本文Vue-cli前端项目基于文章:

Vue-cli搭建项目(包含Node.js安装和ElementUI安装)_小俱的一步步的博客-CSDN博客

后端javaEE项目基于文章:

创建web后端程序(servlet程序搭建)_小俱的一步步的博客-CSDN博客

一、前端登录发起请求

1.安装axios,使用框架

        axios 是一个 HTTP 的网络请求库,安装 npm install axios;

        在 main.js 中配置 axios,导入网络请求库:import axios from 'axios';

        设置访问后台服务器地址:axios.defaults.baseURL="http://127.0.0.1:8080/webBack/";

        将 axios 挂载到 vue 全局对象中,使用 this 可以直接访问:Vue.prototype.$http=axios;

//网络请求
//导入 axios
import axios from 'axios';
//设置访问后台服务器地址
axios.defaults.baseURL = "http://127.0.0.1:8080/webBack/";
//将 axios 挂载到 vue 全局对象中,使用 this 可以直接访问
Vue.prototype.$http = axios;

2.组装请求数据:

        在Login(登录)组件中获取前端数据:

      data() {
			return {
				form: {
					account: '',
					password: ''
				}
			}
		},

        由于向前端提供的数据为json格式,后端不识别,因此将json对象序列化为键=值&键=值:

	//将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);
	}

二、后端请求接收

        创建LoginServlet 类继承 HttpServlet 类,req.getParameter("")接收前端数据

三、连接数据库

1.创建数据库,创建管理员表

CREATE DATABASE web_db CHARSET utf8

CREATE TABLE admin(
	id INT PRIMARY KEY AUTO_INCREMENT,
	account VARCHAR(20) UNIQUE,
	PASSWORD VARCHAR(20)
)

封装用户信息:创建Admin类 属性有int id,String account,String password;生成Getter ,Setter方法。

2.jdbc连接数据库:

import java.sql.*;

public class LoginDao {
    public Admin login(String account, String password) throws ClassNotFoundException, SQLException {
        Connection connection = null;
        PreparedStatement ps = null;
        Admin admain = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");//初始化驱动程序
            String url ="jdbc:mysql://127.0.0.1:3306/web_db?serverTimezone=Asia/Shanghai";
            String uname="root";
            String pwd ="123456";
            connection = DriverManager.getConnection(url,uname,pwd);
            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()){
                admain = new Admin();
                admain.setId(rs.getInt("id"));
                admain.setAccount(rs.getString("account"));
            }
        }finally {
            if (connection!=null){
                connection.close();
            }
            if (ps!=null){
                ps.close();
            }
        }
        return admain;
    }
}

        本次后端项目目录: 

 

其中LoginDao放在dao包中 ,Admin放在model包中。

四、后端响应

1.接收到dao返回的查询数据

2.进行数据封装,创建一个CommonResult类,封装后端数据,必须有get、set方法 ,否则转json时会报错,三个属性:

    private int code;//自定义状态码
    private Object data;//数据
    private String message;//消息

3.进行逻辑判断: 根据前端传入的admin数据进行判断,并响应自定义的状态码,都是用封装的CommonResult类转为json格式传递。

后端接收和响应代码:

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;



public class LoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String account = req.getParameter("account");
        String password = req.getParameter("password");
        System.out.println(account+":"+password);
        //设置响应代码
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter printWriter = resp.getWriter();
        CommonResult commonResult = null;
        try{
            LoginDao loginDao = new LoginDao();
            Admin admin = loginDao.login(account,password);
            if (admin!=null){
                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);
    }
}

五、前端处理

1.接收后端响应的数据:resp.data接收

this.$http.get("back/test").then((resp) => {
		if (resp.data.code == 200) {

		}
}

2.前端路由跳转:登录账号密码与数据库中的匹配,页面跳转到/main,也就是路由跳转,在index.js中配置。

//路由导航守卫,每次进行路由跳转时,就会自动的执行此段逻辑
rout.beforeEach((to, from, next) => {
	if (to.path == '/') {//由于自己定义的login组件的地址为“/”
		// 如果用户访问的登录页,nest直接放行
		return next();
	} else {
		var account = sessionStorage.getItem("account");
		if (account == null) {
			return next("/");
		} else {
			next();
		}
	}
});

3.前端存储用户信息:在生命周期函数中储存账号account

mounted() {
			this.account = sessionStorage.getItem("account");
}

4.在main组件中显示用户账号:在Main组件中的mounted()中存储账号信息并在页面显示管理员账号(双向绑定)。

六、在前端验证用户是否登录

如果没有登录就不能访问/main页面,仍停留到login登录页面;在前端router中index.js添加路由导航守卫,在每次路由跳转时进行判断。

rout.beforeEach((to, from, next) => {
	if (to.path == '/') {//由于自己定义的login组件的地址为“/”
		// 如果用户访问的登录页,nest直接放行
		return next();
	} else {
		var account = sessionStorage.getItem("account");
		if (account == null) {
			return next("/");
		} else {
			next();
		}
	}
});

七、web会话跟踪

http是无状态的,登录完成后客户端与服务器断开了连接,之后再向后端发送请求,后端就不知道是哪个客户端发送的。

使用会话跟踪:

1.登录 向后端发送账号和密码

2.后端与数据库连接验证账号密码

3.如果账号正确,在后端生成一个token(唯一的一种字符串),把token响应给前端,用JWT生成token。

Base64:将八个bit位一组改为六个bit位一组。

JWT组成的三部分:

第一部分头部(header),第二部分载荷(payload, 用户的信息),第三部分签证(signature)。

步骤:将JWT两个jar包加载到后端里

将生成的token存到admin中(即添加token属性),传到前端去。

生成token的工具类:

/**
 * JWT工具类
 */
public class JWTUtil {

    /**
     * 根据用户id,账号生成token
     * @param u
     * @return
     */
    public static String getToken(Admin u) {
        String token = "";
        try {
            //过期时间 为1970.1.1 0:0:0 至 过期时间  当前的毫秒值 + 有效时间
            Date expireDate = new Date(new Date().getTime() + 20*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",u.getId())
                    .withClaim("account",u.getAccount())
                    .withExpiresAt(expireDate)
                    .sign(algorithm);
        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
        return token;
    }

    /**
     * 验证token是否有效
     * @param token
     * @return
     */
    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部分数据,按需使用
     * @param token
     * @return
     */
    public static DecodedJWT getTokenInfo(String token){
        return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
    }

}

4.前端存储token:sessionStorage.setItem("adminToken", resp.data.data.token);

5.之后每次请求,都将token携带者向后端发送。

6.后端的java对请求中的token进行解析验证。

写一个过滤器将每次拿到的token进行验证。

public class AdminTokenFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("token验证过滤器");
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String adminToken = request.getHeader("adminToken");
        boolean verify = JWTUtil.verify(adminToken);
        if (verify){//token验证没有问题
            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);
        }
    }
}

八、请求拦截器和响应拦截器

在main.js中配置两个拦截器

请求拦截器:每发送一次http请求,都会执行此拦截器

axios.interceptors.request.use(config => {
	//为请求头对象,添加 Token 验证的 token 字段
	config.headers.adminToken = window.sessionStorage.getItem('adminToken');
	return config;
})

响应拦截器:

axios.interceptors.response.use((resp) => {
	if(resp.data.code == 500){
		ElementUI.Message({
			message:resp.data.message,
			type:"error"
		})
	}
	if(resp.data.code == 401){
		ElementUI.Message({
			message:"token验证失败",
			type:"error"
		})
		router.replace("/");
	}
	return resp;
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/607151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2. requests.get()函数访问网页(小白入门)

2. requests.get()函数访问网页(小白入门) 文章目录 2. requests.get()函数访问网页(小白入门)1. 人工访问网页2. 爬虫第一步&#xff1a;发起网络请求3. requests库的安装4. requests.get()函数&#xff1a;发送网络请求5. 代码解析1. 导入库的语法2. 指定网址3. 发送请求4. 输…

chatgpt赋能python:Python取消撤销——让你的代码更加高效

Python取消撤销——让你的代码更加高效 在Python编程的过程中&#xff0c;经常会出现需要撤销操作的场景。但是&#xff0c;在一些复杂的代码编辑器中&#xff0c;常规的CtrlZ撤销操作可能无法满足你对代码精度的要求。为此&#xff0c;Python取消撤销就应运而生。 Python取消…

多变量系统的最小二乘辨识问题的推导以及matlab仿真

1.单输入单输出情况的推导;2.两输入两输出情况的推导,并进行matlab仿真以及完成仿真报告。 多变量系统的最小二乘辨识问题是确定一个线性多输入多输出(MIMO)系统的未知参数,使得该系统能够以最佳方式近似给定输入和输出之间的关系。在本例中,我们将展示单输入单输出(SIS…

软件外包开发的测试用例

软件测试用例是一组详细的步骤、输入数据、预期结果和实际结果&#xff0c;用于验证软件是否满足特定需求或功能。编写测试用例的目的是确保软件的质量和性能。今天和大家分享编写软件测试用例的一般步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;…

解决record on line 2: wrong number of fields

背景 基于"encoding/csv"库解析。 共解析多个文档&#xff0c;只有这一个解析有问题&#xff0c;所用代码一致&#xff0c;进行比较后 发现该文档和其它文档不同&#xff0c;其它文档是第一行就是列名&#xff0c;下面都是数据&#xff1b; 而这个文档前两行有数据且…

k8s部署Elasticsearch集群+Kibana方案--开启X-Pack 安全认证

前言 本文中使用StatefulSet 方式部署 Elasticsearch 集群&#xff0c;并且开启X-Pack 安全认证&#xff0c;存储使用的是NFS&#xff0c;属于一个初学者自己探索的方案&#xff0c;如果有比较好的方案&#xff0c;还请不吝评论赐教。 版本说明&#xff1a; Kubernetes v1.25…

微信小程序uniapp医患管理系统预约挂号就诊处方满意评价系统

从系统开发环境、系统目标、设计流程、功能设计等几个方面对系统进行了系统设计。开发出本医患关系管理系统&#xff0c;主要实现了管理员后端&#xff1b;首页、个人中心、用户管理、医生管理、医生信息管理、患者信息管理、预约就诊管理、就诊信息管理、投诉管理、投诉反馈管…

【走进Linux的世界】Linux---基本指令(2)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【Linux专栏】&#x1f388; 本专栏旨在分享学习Linux的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 ls *man指令小…

redis缓存穿透、缓存雪崩 、缓存击穿

一、缓存穿透、缓存雪崩 、缓存击穿 摘自尚硅谷文档 1、缓存穿透 缓存穿透是指查询一个一定不存在的数据&#xff0c;由于缓存是不命中&#xff0c;将去查询数据库&#xff0c;但是数 据库也无此记录&#xff0c;我们没有将这次查询的 null 写入缓存&#xff0c;这将导致这个…

Spin加载中(antd-design组件库)loading效果简单使用

1.Spin加载中 用于页面和区块的加载中状态。 2.何时使用 页面局部处于等待异步数据或正在渲染过程时&#xff0c;合适的加载动效会有效缓解用户的焦虑。 组件代码来自&#xff1a; 加载中 Spin - Ant Design 3.本地验证前的准备 参考文章【react项目antd组件-demo:hello-world_…

PyTorch深度学习实战(2)——PyTorch基础

PyTorch深度学习实战&#xff08;2&#xff09;——PyTorch基础 0. 前言1. 搭建 PyTorch 环境2. PyTorch 张量2.1 张量初始化2.2 张量运算2.3 张量对象的自动梯度计算 3. PyTorch 张量相对于 NumPy 数组的优势小结系列链接 0. 前言 PyTorch 是广泛应用于机器学习领域中的强大开…

AutoHotKey脚本初步:判断和选择

文章目录 脚本基础连击识别setTimer判断和选择 脚本基础 尽管通过窗口识别与按键映射&#xff0c;就可以胜任很多工作了&#xff0c;但AutoHotKey仍提供了一些简单的编程功能&#xff0c;对一些稍微复杂的任务&#xff0c;也可以做到得心应手。但要注意一点&#xff0c;AHK的V…

【操作系统】Linux 中的 Page Cache

【操作系统】Linux 中的 Page Cache 参考资料&#xff1a; 文件 I/O 简明概述 - page cache 进程写文件时&#xff0c;进程发生了崩溃&#xff0c;已写入的数据会丢失吗&#xff1f; Linux Page Cache 调优在 Kafka 中的应用 【操作系统】一文带你深入浅出零拷贝技术 【操作系…

大数据Doris(三十四):Doris配置Spark与Yarn

文章目录 Doris配置Spark与Yarn 一、Doris配置Spark 1、配置 SPARK_HOME 环境变量 2、配置SPARK 依赖包

JavaScript之BOM(八)

JavaScript之BOM 1、BOM中的对象2、window对象2.1、简介2.2、常用的属性与方法2.3、常用的事件2.4、定时器和延时器 3、navigator 常用属性与方法4、history 常用属性与方法5、location 常用属性与方法 BOM&#xff1a;浏览器对象模型&#xff08;Browser Object Model&#xf…

交直流系统潮流计算及相互关联特性分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

chatgpt赋能python:Python取消合并单元格

Python取消合并单元格 在Excel中&#xff0c;合并单元格是一个非常常见的操作&#xff0c;它可以将多个单元格合并成一个单元格。这样可视化效果会更好&#xff0c;但是实际上会影响数据的计算和操作。如果你想取消这个操作&#xff0c;手工操作可能会非常费时间。不过&#x…

chatgpt赋能python:Python变量赋值

Python 变量赋值 在 Python 中&#xff0c;我们可以使用多种符号来给变量赋值。本文将介绍这些符号以及它们在编程中的应用。 等号&#xff08;&#xff09; 在 Python 中&#xff0c;我们最常用的符号是等号&#xff08;&#xff09;&#xff0c;它可以将一个值赋给一个变量…

Image fusion based on generative adversarial network consistent with perception

1.摘要 深度学习是红外和可见光图像融合领域中快速发展的方法。在这个背景下&#xff0c;密集块在深层网络中的使用显著提高了浅层信息的利用率&#xff0c;并且生成对抗网络&#xff08;GAN&#xff09;的组合也提高了两个源图像的融合性能。我们提出了一种基于密集块和GAN的…

“吴军讲ChatGPT“课程的个人总结

人工智能时代, ChatGPT如此火热, 大家恐慌, 焦虑, 大家最关注的是两个问题 我会不会被取代?我有没有机会? 吴军老师(浪潮之巅, 数学之美等), 有门课程, <吴军讲ChatGPT>, 用通俗易懂的语言, 讲解了人工智能的技术原理前世今生,以及当下火热的ChatGPT的可以做什么, 那…