位置: IT常识 - 正文

前后端分离式交互(前后端分离弊端)

编辑:rootadmin
前后端分离式交互 目录

前言

1.javaEE环境安装

第一步:正常创建javase项目

第二步:右击项目,引入框架支持

第三步:将项目部署到Tomcat服务器上。Tomcat安装及配置

2.servlet搭建

请求格式为:ip:端口/项目名/servlet地址

3.servlet生命周期

4.http请求和响应

         4.1http请求

         4.2http响应:

5.过滤器(Filter)

6.异步请求(Ajax)+跨域问题

        6.1异步请求

        6.2跨域问题

         6.2.1什么是跨域?

         6.2.2为什么要跨域?

         6.2.3后端怎么解决跨域问题?

7.前端过渡

8.json数据格式+前端数据请求格式问题

       8.1后端数据响应json处理

       8.2前端请求数据格式处理

9.后端验证用户名和密码(联系数据库查询)

       9.1Reult类

       9.2User类

       9.3JDBC代码

       9.4.LoginServlet类

10.前端收到响应判断是否登录+sessionstorage+localStorage

     10.1前端接收到json字符串,做出判断

     10.2sessionstorage+localStorage

        10.2.1提出问题:

        10.2.2问题分析:

        10.2.3解决问题:

        10.2.4路由导航守卫

11.会话跟踪

    11.1token是怎么生成的?

    11.2token优点

    11.3base64转码

    11.4后端生成token并响应

    11.5前端接收到token后存储,并且请求时将token放在请求头

        11.5.1存储:

        11.5.2前端发送请求时(axios请求拦截):

    11.6后端通过过滤器中统一验证

    11.7前端接收到验证响应做出判断(axios响应拦截)


前言

推荐整理分享前后端分离式交互(前后端分离弊端),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:前后端分离式交互技术,前后端分离的作用,前后端分离原理,前后端分离优点,前后端分离与不分离,前后端分离式交互技术,前后端分离式交互,前后端分离式交互技术,内容如对您有帮助,希望把文章链接给更多的朋友!

        现在前端和后端已经完全分离,本篇文章会从javaEE环境的安装一直到会话跟踪结束,搭建一个学生管理系统的登录需求,实现前后端的基本交互。至于前端登录页面的搭建,是来源于于之前的文章前端项目框架的搭建(Vue.js+ElementUI骨灰级保姆教程)。切记细细理解代码中的注释!!!

1.javaEE环境安装

        项目是在IntelliJ IDEA 2020.2.1 版本下创建的。

第一步:正常创建javase项目

第二步:右击项目,引入框架支持

        选择Web Application(4.0) ,点击ok

         文件介绍

 第三步:将项目部署到Tomcat服务器上。Tomcat安装及配置

 

        Server设置成这样。 

 

        在Deployment 添加创建的项目。

 

完成此操作后,项目即已部署在服务器上。

2.servlet搭建

        导入servlet-api.jar包

        首先我们创建一个servlet包,里面创建LoginServlet类,此类继承HttpServlet类,在里面生成四个方法,分别是构造方法、init(ServletConfig config)、service()、destroy()。

import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServlet;import java.io.IOException;public class LoginServlet extends HttpServlet { public LoginServlet() { System.out.println("无参构造方法"); } @Override public void init(ServletConfig config) throws ServletException { System.out.println("初始化Servlet"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service"); } @Override public void destroy() { System.out.println("destroy"); }}

        在xml文件中配置LoginServlet。

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置项目中的LoginServlet--> <servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>servlet.LoginServlet</servlet-class><!--LoginServlet在项目所处的位置--> </servlet> <!--为LoginServlet配置访问地址--> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/login</url-pattern><!--地址以/开头--> </servlet-mapping></web-app>

        然后启动服务器,在浏览器中访问:

请求格式为:ip:端口/项目名/servlet地址

         回车后,我们可以发现在后端输出框中输出了:

无参构造方法 初始化Servlet service

        为啥会输出这些?这就牵扯到了servlet生命周期~~~~~ 

3.servlet生命周期

         访问路线:

         方法解析:

package servlet;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServlet;import java.io.IOException;/*!!!无论什么时侯创建,创建的servlet对象指向的是servlet地址, servlet什么时候被创建: 小于0:第一次访问服务器时,大于等于0:在服务器启动时 <load-on-startup>-1</load-on-startup> 在xml中配置 创建对象后就直接会执行构造方法和init(),之后访问到地址时(即通过浏览器-服务器-项目-地址),才会 执行service()等一系列方法。*//* * 一次http请求发送到后端找到Servlet程序,是按照一个特定的顺序调用方法 * 在最上层LoginServlet实现了Servlet接口,所有的javaEE的类都实现了Servlet接口,一切按照Servlet接口中定义方法的顺序来走。 */public class LoginServlet extends HttpServlet { // 构造方法() 最先执行 一次 初始化对象的,主要是针对成员变量 public LoginServlet() { System.out.println("无参构造方法"); } //init(ServletConfig config) 在构造方法之后就会执行 一次 初始化servlet,主要是针对配置文件,可获取到配置文件中定义的参数parameter,然后可通过config调用 /*<init-param> <param-name>zhangsan</param-name> <param-value>123</param-value> </init-param> */ @Override public void init(ServletConfig config) throws ServletException { System.out.println("初始化Servlet"); } //service() 每次请求都会执行,提供服务的。 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service"); } //destroy() 在服务器关闭时执行,只执行一次。比如将一些数据存储到数据库,打印日志信息。 @Override public void destroy() { System.out.println("destroy"); }}4.http请求和响应

         由于前端发送的http请求有get和post两种,所以后端提供doGet()和doPost()进行相应的处理和响应。

4.1http请求

        请求中包含:

请求行请求的地址,请求的方式,请求的状态。请求头包含服务器信息,客户端信息,以键值对的形式向后端发送,键都是固定的。请求体存放post请求方式向服务器端发送的数据。

        http请求的两种方式:

get:

          1.get方式主要用于从服务器获取数据,也是可以向服务器发送数据的后端地址?键=值&键=值。          2.不能传递过多的数据,因为浏览器会限制  一般情况 1-2kb。          3.请求的数据在地址后面显示的,不能传递敏感数据,安全性低。

         4.tomcat8之后,get请求中有中文,不会乱码。                     

post:        1.post主要用于向后端发送请求,请求的数据存放在请求体中,不会显示在地址栏中。        2.相对安全,传输的数据量大,没有限制(可以通过post提交文件)。 

       3.后端接受前、响应前需要设置编码,要不然接受时会乱码。setCharacterEncoding(编码格式)。

4.2http响应:

        1.Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个代表响应的HttpServletResponse对象。

        2.用getWriter()获得一个PrintWriter字符输出流输出数据                3.response.setContetnType("text/html;charset=utf-8");方法可以同时设定response所使用的字符集编码和浏览器打开所用的字符集编码。

        前端发送(举例):

<!DOCTYPE html><html><head><meta charset="utf-8" /><title></title></head><body> <!--get方式--><a href="http://127.0.0.1:8080/webBack_Test/login?name=ami&age=20">同步访问后端</a> <!--post方式--><form action="http://127.0.0.1:8080/webBack_Test/login" method="post">用户名<input type="text" name="username" value="" />密码<input type="password" name="password" value="" /><input type="submit" value="登录"/></form></body></html>

         后端接收:

public class LoginServlet extends HttpServlet { /* 虽然调用doGet和doPost方法,但是构造,init,service,destroy方法,仍然会正常执行,这是Servlet接口的规范,是不能变的!! 其实父类的service方法,里面是会进行一个判断的,判断请求方式是get还是post,然后调用doGet()或者doPost()方法, 只不过之前我们在本类中又重写了service方法,使他的实际功能没有体现出来。 当一次http请求发送到服务器时,tomcat会将请求的所有数据封装到一个类当中,而这个类实现了HttpServletRequest接口。 * */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* get与post的接收顺序,步骤一样,就是doGet里面不用设置编码 * */ } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收请求数据(请求行,请求头,请求体) req.getRequestURL();//http://127.0.0.1:8080/webBack_Test/login req.getRemoteAddr();//获取远端的ip地址 127.0.0.1 req.getRemotePort();//获取远端的端口 //接收用户自己发来的数据.post数据在接受之前,需要设置一个解码规则 req.setCharacterEncoding("utf-8"); req.getParameter("username"); req.getParameter("password"); //处理 //响应 //resp.setContentType("text/html;charset=utf-8");设置编码 resp.setHeader("Content-Type","text/html;charset=utf-8"); PrintWriter writer = resp.getWriter();//获取打印流 writer.print("提交成功"); //对象,集合,map-->以后用json //print与write没区别,就是print的方法重载比较多 }}5.过滤器(Filter)

        我们知道在前端发送post请求时,后端接收时要先设置编码,以防止乱码,如果项目中servlet包有多个类时,每一个在接受前都要手动设置一下编码,岂不繁琐。所以我们提出过滤器。

        Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。

      Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Servlet, 从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

      ● doFilter(ServletRequest request, ServletResponseresponse,FilterChain chain):该方法是filter进行过滤操作的方法,是最重要的方法。

      ●  filterChain过滤链,处理完后,让请求继续向下执行,下一个可能时目标Servlet,也可能是下一个过滤器。         filterChain.doFilter(servletRequest,servletResponse);

        作用:对服务器web资源进行拦截(权限控制,通过拦截资源进行权限控制,是否可以访问)

         即浏览器访问服务器时,可以进入过滤器1、也可访问servlet地址。如果进入到过滤器1后,可以继续进到过滤器2、也可直接截止做出响应、也可继续访问servlet地址,都是我们可以设置的!

        所以我们可以创建一个filter包里面创建一个设置编码的过滤器(类),让每次请求先通过编码过滤器,设置编码。

/*编码过滤器*/public class EncodeFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); //filterChain过滤链,处理完后,让请求继续向下执行,下一个可能时目标Servlet,也可能是下一个过滤器 filterChain.doFilter(servletRequest,servletResponse); }}

       在xml文件中配置过滤器:配置/*表示所有请求都得过此过滤器

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置项目中的LoginServlet--> <servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>servlet.LoginServlet</servlet-class><!--LoginServlet在项目所处的位置--> </servlet> <!--为LoginServlet配置访问地址--> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/login</url-pattern><!--地址以/开头--> </servlet-mapping> <!--配置编码过滤器--> <filter> <filter-name>encode</filter-name> <filter-class>filter.EncodeFilter</filter-class> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/*</url-pattern> <!--配置哪些请求地址进入到编码过滤器 /*表示所有--> </filter-mapping></web-app>6.异步请求(Ajax)+跨域问题        6.1异步请求

        说起异步,涉及的领域很广,这里我们探讨异步请求。下面是同步请求和异步请求之间的区别。

前后端分离式交互(前后端分离弊端)

         以前javaScript里的异步请求(用户名失焦验证举例):

<!DOCTYPE html><html><head><meta charset="utf-8"><title></title><script type="text/javascript">function checkusername(username){//最底层代码,是用XMLHtttpRequest对象来发送请求var httpObj = new XMLHttpRequest();httpObj.open("GET","http://127.0.0.1:8080/webBack/login?username="+username,true);httpObj.send(null);//发送请求//接受请求httpObj.onreadystatechange=function(){//就相当于一个状态信息码 从2开始--到4响应结束if(httpObj.readyState==4){document.getElementById("msgId").innerHTML = httpObj.responseText;}} </script></head><body><form action="" method="post">账号<input type="text" name="username" value="" onblur="checkusername(this.value)" /><span id="msgId"></span> <br />密码<input type="password" name="password" value="" /><br /><input type="submit" value="登录"/></form></body></html>

        现在用axios,是一个Ajax框架来进行改进,但是底层还是通过XMLHtttpRequest对象来操作的。此时我们还未把我们所讲的东西整合在Vue-cli(脚手架)项目中,所以我们需要导入一个axios.min.js的js文件。axios.min.js下载

<!DOCTYPE html><html><head><meta charset="utf-8"><title></title><script src="js/axios.min.js" type="text/javascript" charset="UTF-8"></script><script type="text/javascript">function checkusername(username){//将创建XMLHtttpRequest对象的过程封装在了get()里面axios.get("http://127.0.0.1:8080/webBack_Test/login?username="+username).then(function(resp){ //resp就是拿到的一系列响应过来的数据 document.getElementById("msgId").innerHTML = resp.data;});}</script></head><body><form action="" method="post">账号<input type="text" name="username" value="" onblur="checkusername(this.value)" /><span id="msgId"></span> <br />密码<input type="password" name="password" value="" /><br /><input type="submit" value="登录"/></form></body></html>

         运行之后会发现,浏览器发出请求给服务器,可是服务器响应,浏览器接收不到,这就引出了跨域问题。 之前我们同步请求时,服务器的响应是直接响应在浏览器重新生成的窗口上,而异步请求时服务器的响应是要被浏览器给接收到的,然后通过标签响应在此页面上。

        6.2跨域问题            6.2.1什么是跨域?

        跨域是指从一个域名的网页去请求另一个域名的资源,严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域.

        跨域问题是一个前端问题,是在前后分离的架构中出现的。

         6.2.2为什么要跨域?

        有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com , 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。

        6.2.3后端怎么解决跨域问题?

解决办法是创建一个过滤器(CorsFilter)。

import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;//后端解决跨域问题public class CorsFilter implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; //允许携带Cookie时不能设置为* 否则前端报错 //1.本质就是你浏览器在访问服务器时,我后端获取到你浏览器的地址,然后设置前端让前端知道这是一个安全的响应,即后端响应可以到浏览器上 //就比如说,你浏览器是8848的端口,你访问我8080的服务器,我给你做出响应,你不接收,我后端就就要设置8848要可跨域。 httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("origin"));//允许所有请求跨域 httpResponse.setHeader("Access-Control-Allow-Methods", "*");//允许跨域的请求方法GET, POST, HEAD 等 httpResponse.setHeader("Access-Control-Allow-Headers", "*");//允许跨域的请求头 httpResponse.setHeader("Access-Control-Allow-Credentials", "true");//是否携带cookie filterChain.doFilter(servletRequest, servletResponse); }}

在xml中配置cors过滤器。

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置项目中的LoginServlet--> <servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>servlet.LoginServlet</servlet-class><!--LoginServlet在项目所处的位置--> </servlet> <!--为LoginServlet配置访问地址--> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <url-pattern>/login</url-pattern><!--地址以/开头--> </servlet-mapping> <!--配置编码过滤器--> <filter> <filter-name>encode</filter-name> <filter-class>filter.EncodeFilter</filter-class> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/*</url-pattern> <!--配置哪些请求地址进入到编码过滤器--> </filter-mapping> <!--配置解决跨越过滤器--> <filter> <filter-name>cors</filter-name> <filter-class>filter.CorsFilter</filter-class> </filter> <filter-mapping> <filter-name>cors</filter-name> <url-pattern>/*</url-pattern> </filter-mapping></web-app>7.前端过渡

        现在我们把Ajax加到我们之前用vue写的前端项目(vue-cli)里面,项目是之前用脚手架方式搭建的,感兴趣的友友们可以看一下:前端项目框架的搭建(Vue.js+ElementUI骨灰级保姆教程)。

        在终端中输入命令:npm install axios

        之前我们在main.js里面导入了路由和ElementUI框架,现在把axios也加进去。 

       

        发送post请求方式为:

this.$http.post("请求地址",需要传输的数据).then((resp)=>{          });

8.json数据格式+前端数据请求格式问题        8.1后端数据响应json处理

        JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,是为了在不同语言间传输数据方便,我们知道java和javaScript的语法是不一样的,那么我们在前后端之间的数据传输就要用到json。

        转换代码: 

ObjectMapper objectMapper = new ObjectMapper();    //创建对象 String json = objectMapper.writeValueAsString(响应的数据);//将响应的数据转化为字符串

       利用writeValueAsString()方法可以将要响应的数据,例如对象,转化为一个json字符串,前端接收到json字符串后,自动会转换为js对象。

        例如:

{"code":200,"data":{"id":1,"username":"zhangsan","password":null},"msg":"登录成功"}

        要使用json数据交换格式,我们需要在lib目录里面导入6个json的jar包。

         8.2前端请求数据格式处理

        我们在用vue框架前,前端请求数据都是以键值对的,例如 username = "  ",这样后端就用getparameter("键名")方法,能够获取到数据。而当我们使用了vue框架后,里面的数据格式会不同,例如 usernam : "  ",这样就会导致数据传输到后端,但是后端getparameter("键名")方法读取不到。所以我们要在前端对数据进行处理。我们自定义一个转换函数~~~

//序列化为键=值&键=值

function jsonToString(jsonobj){            console.log(jsonobj)            var str = "";            for(var s in jsonobj){                 str+=s+"="+jsonobj[s]+"&";                  }            return str.substring(0,str.length-1);        }

 即发送请求方式为:

         this.$http.post("login",jsonToString(this.ruleForm)).then((resp)=>{  });

ruleForm为我们提交的表单中的数据,里面包含username,password。

9.后端验证用户名和密码(联系数据库查询)

        结合上面我们所讲的知识,联系起来,搭建基本的后端代码。

                9.1Reult类

        为了响应数据格式统一,我们创建一个Reuslt类,用来封装每次后端响应的数据。

public class Result { int code;//200成功 201失败 Object data;//数据 user对象 String msg; //信息提示 public Result(int code, Object data, String msg) { this.code = code; this.data = data; this.msg = msg; } 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 getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public static Result success(Object data){ //操作成功 return new Result(200,data,"登录成功"); } public static Result warn(){ //登录失败 return new Result(201,null,"账号或密码错误"); } public static Result error(String msg){ //出现异常 return new Result(500,null,msg); }}      9.2User类

        查询前实例化一个user对象,将查询的结果储存在user里面,没查询到user即为null

public class User { private int id; private String username; private String password; private String token; //会话跟踪处要用 public User() { } public User(int id, String username, String password) { this.id = id; this.username = username; this.password = password; } 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 getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; }}        9.3JDBC代码

        联系数据库、通过JDBC查询返回User。代码相信大家都能理解,不做过多解释。

public class LoginDao { static Connection con = null; static PreparedStatement pst = null; static ResultSet rs = null; public static User find(String username,String password) throws SQLException { User user = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai", "root", "root"); String sql = "select * from user where username = ? and password =?"; pst = con.prepareStatement(sql); pst.setObject(1,username); pst.setObject(2,password); rs = pst.executeQuery(); while (rs.next()) { user = new User(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(null); } } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); }finally { if(con!=null){ con.close(); } if(pst!=null){ pst.close(); } if(rs!=null){ rs.close(); } } return user; }}        9.4.LoginServlet类

        通过ObjectMapper对象,将result转化为json字符串,响应到前端。

public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Result result = null; //要通过编码过滤器,所以不用设置编码。 //接收数据 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); //打印一下,以便于看一下后端接收到前端发送的数据了没 System.out.println(password); //设置响应编码 resp.setHeader("Content-Type","text/html;charset=utf-8"); //获取打印流 PrintWriter writer = resp.getWriter(); //处理 访问dao 与数据库交互,根据返回的结果向客户端响应内容 try { User user = LoginDao.find(username,password); if(user!=null){ result = Result.success(user); }else { result = Result.warn(); } } catch (SQLException e) { e.printStackTrace(); result = Result.error("系统忙"+e.getMessage()); } //两种语言间对象结构不同,需要一种标准格式进行数据传输,json是一个轻量级的格式。 ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(result); System.out.println(json); writer.print(json); }}10.前端收到响应判断是否登录+sessionstorage+localStorage       10.1前端接收到json字符串,做出判断 //如果发送成功,在此向用户提示,并跳转到登陆成功的组件this.$http.post("login",jsonToString(this.ruleForm)).then((resp)=>{//resp.data = Result 前端接收到json字符串后,自动会转换为js对象。 resp.data其实就是拿到了json字符串,只不过它可以看作是user对象if(resp.data.code==200){//直接跳转 this.$message({message: '登录成功',type: 'success'});//提示信息都是ElementUI里面的 this.$router.push("/main"); //路由切换,切换进主页面 }else if(resp.data.code==201){ this.$message({message:resp.data.msg,type: 'warning'});//提示信息}else{ this.$message.error(resp.data.msg);//提示信息}});    10.2sessionstorage+localStorage

        我们现在实现了到登录界面输入用户名和密码,然后提交表单到后端,后端查询后做出响应给前端,前端做出判断是否登录成功。

        10.2.1提出问题:

        但是现在有个问题,就是如果我们不通过登录页面,而是直接访问主界面,那么也会访问的到,并且如果我们关闭主界面,或者退出主界面,然后再访问主界面,它依旧是可以直接跳转到主界面,没有通过登录就可以访问主界面,这些显然是不切合实际的。

        10.2.2问题分析:

        那我们试想有没有这样一种东西,我们每次登录成功后把用户名存在浏览器里面,然后每次跳转到其他页面(除过跳转登录页面)时,我都要做一次判断,看一下浏览器里面有没有用户名信息,如果没有的话,则跳转至登录页面,表示要重新登陆!

        10.2.3解决问题:sessionstorage浏览器提供的一个会话级别的存储空间,浏览器关闭后立刻消失.setItem("键",值);localStorage长久保存到浏览器。只能手动清除setItem("键",值)

         这里用sessionstorage就可以解决我们的问题:sessionStorage.setItem("username",用户名);

登录成功后将用户名信息存储即可,不仅在关闭页面后,需要清空存储。我们还得在主界面退出登

录的时候也得将存储清空。

         主界面退出函数:

exit(){this.$confirm('你确定要退出此窗口?', '提示', { confirmButtonText: '确定', type: 'warning'}).then(() => {sessionStorage.clear();//清除sessionStorage缓存 this.$router.push("/login"); }); }

        改进过后的登录判断(将用户名信息存储):

//如果发送成功,在此向用户提示,并跳转到登陆成功的组件this.$http.post("login",jsonToString(this.ruleForm)).then((resp)=>{//resp.data = Result 前端接收到json字符串后,自动会转换为js对象。 resp.data其实就是拿到了json字符串,只不过它可以看作是user对象if(resp.data.code==200){//直接跳转 sessionStorage.setItem("username",resp.data.data.username); this.$message({message: '登录成功',type: 'success'});//提示信息都是ElementUI里面的 this.$router.push("/main"); //路由切换,切换进主页面 }else if(resp.data.code==201){ this.$message({message:resp.data.msg,type: 'warning'});//提示信息}else{ this.$message.error(resp.data.msg);//提示信息}});         10.2.4路由导航守卫

        在我们路由(页面)每次想跳转时,我们都要自己在要切换的路由里mounted(当vue对象于标签绑定完毕后执行,类似于onload事件)添加判断信息:

mounted(){this.username = sessionStorage.getItem("username");if(this.username==null){ this.$router.push("/login");} }

        这样特别麻烦,因为在我们的主界面得有很多操作,都得添加判断,在这我们引出路由导航守卫来改进。在router目录里index.js文件里添加。文件在前端项目框架的搭建(Vue.js+ElementUI)

里面都有讲过。感兴趣的友友可以了解一下~~~

import Vue from 'vue';import router from 'vue-router'; /* 导入路由*//* 导入组件 */import Login from "../Login.vue"; //../返回上一级目录import Main from "../Main.vue";Vue.use(router);/* 定义组件路由 */var rout = new router({routes: [{path: '/login', //为组件定义地址name: 'Login', //自己起一个名字 也可以不用起名component: Login //与上面导入的名字必须对应一致},{path: '/main',component: Main}]}); //在router里面的index.js文件里加入路由导航守卫,每次发生路由时触发//to:要访问的路由 from:请求访问的路由 next:跳转rout.beforeEach((to,from,next)=>{if(to.path=='/login'){ //如果用户访问的登录页,直接放行return next();}else{var username = sessionStorage.getItem("username");if(username==null){return next("/login");//跳转到登录页面}else{return next();//继续}}}) //导出路由对象export default rout;11.会话跟踪

        因为http的请求都是无状态的(请求--响应的模式),请求中并没有能识别对方身份的标识,那么我们在实际开发中就要解决这个问题,假如:我们在网上购物,虽然我们登录过了,然后点击付款,这个付款请求中没有携带用户信息,所以后端不知道是哪个用户请求的。

        这个实现的功能称为web会话跟踪技术。

      11.1token是怎么生成的?

        token是由三部分组成,第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 用户的信息),第三部分是签证(signature),将这三段信息文本用.链接一起就构成了token字符串。

        例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

        头信息(header):

完整的头部就像下面这样的JSON:

 {

  'typ': 'JWT',             

本文链接地址:https://www.jiuchutong.com/zhishi/298921.html 转载请保留说明!

上一篇:【深度学习】pix2pix GAN理论及代码实现与理解

下一篇:web自动化测试入门篇06 —— 元素定位进阶技巧(web自动化测试平台)

  • 两点论淘宝客该如何推广(淘宝客对店铺有好处吗)

    两点论淘宝客该如何推广(淘宝客对店铺有好处吗)

  • ios15密码怎么改4位(ios密码改成4位数)

    ios15密码怎么改4位(ios密码改成4位数)

  • nvarchar是什么数据类型(nvars是什么)

    nvarchar是什么数据类型(nvars是什么)

  • 苹果11怎么设置小圆点(苹果11怎么设置密码锁屏)

    苹果11怎么设置小圆点(苹果11怎么设置密码锁屏)

  • 东芝a3和v9有什么区别(东芝a3和v9v10哪个产品新)

    东芝a3和v9有什么区别(东芝a3和v9v10哪个产品新)

  • 无法检测到拨号调制解调器什么意思(无法检测到拨号调节器)

    无法检测到拨号调制解调器什么意思(无法检测到拨号调节器)

  • 华为手机出厂贴的是什么膜(华为手机出厂贴膜要撕掉吗)

    华为手机出厂贴的是什么膜(华为手机出厂贴膜要撕掉吗)

  • 一个手机号码可以绑定几个QQ(一个手机号码可以绑定几个支付宝账户)

    一个手机号码可以绑定几个QQ(一个手机号码可以绑定几个支付宝账户)

  • e5相当于i几处理器(e5的处理器怎么样)

    e5相当于i几处理器(e5的处理器怎么样)

  • h61主板配什么独立显卡(h61主板搭配)

    h61主板配什么独立显卡(h61主板搭配)

  • 为什么抖音有的显示在线有的不显示(为什么抖音有的视频不能保存至相册)

    为什么抖音有的显示在线有的不显示(为什么抖音有的视频不能保存至相册)

  • 摩托罗拉折叠手机什么时候上市(摩托罗拉折叠手机最新款)

    摩托罗拉折叠手机什么时候上市(摩托罗拉折叠手机最新款)

  • wps和ppt什么区别(ppt和wps office)

    wps和ppt什么区别(ppt和wps office)

  • 小米路由器不稳定解决(小米路由器不稳定 网络断断续续)

    小米路由器不稳定解决(小米路由器不稳定 网络断断续续)

  • 微店是微信的吗(微店是微信开的吗)

    微店是微信的吗(微店是微信开的吗)

  • 微机总线包括(微机总线包括哪两部分)

    微机总线包括(微机总线包括哪两部分)

  • qq密码多久能改回最近使用的密码(qq密码多久能改过来)

    qq密码多久能改回最近使用的密码(qq密码多久能改过来)

  • word系统是一种什么软件(word属于什么系统)

    word系统是一种什么软件(word属于什么系统)

  • 200m宽带下载速度多少mbps(200m宽带下载速度应该是多少)

    200m宽带下载速度多少mbps(200m宽带下载速度应该是多少)

  • 华为手机如何定位苹果手机(华为手机如何定位苹果手机位置)

    华为手机如何定位苹果手机(华为手机如何定位苹果手机位置)

  • 手机怎么控制路由器(手机怎么控制路由器开关)

    手机怎么控制路由器(手机怎么控制路由器开关)

  • iphone11哪天上市(苹果11什么时候上市发售最新的手机)

    iphone11哪天上市(苹果11什么时候上市发售最新的手机)

  • 抖音动态什么意思(抖音里面的动态是什么意思)

    抖音动态什么意思(抖音里面的动态是什么意思)

  • 关闭华为手机盲人模式有没有简单的方法(华为手机怎么关闭盲点)

    关闭华为手机盲人模式有没有简单的方法(华为手机怎么关闭盲点)

  • Mac电脑finder是什么意思 Mac Finder的10个使用技巧(苹果电脑里的finder是什么)

    Mac电脑finder是什么意思 Mac Finder的10个使用技巧(苹果电脑里的finder是什么)

  • Vue懒加载(vue懒加载机构树刷新)

    Vue懒加载(vue懒加载机构树刷新)

  • 羊了个羊通关助手(羊羊 过好)

    羊了个羊通关助手(羊羊 过好)

  • 股权转让企业所得税纳税地点
  • 海关关税计算公式
  • 纳税人对所提交信息的什么负责
  • 一般纳税人金税盘抵税会计分录
  • 支付土地补偿款怎么做账务处理
  • 本月发生费用下月收到发票
  • 水利基金应税项和减除项
  • 从合伙企业分回的经营所得 合伙企业 个人所得税
  • 非流动资产处置损失属于什么会计科目
  • 企业支付的
  • 水资源税怎么入账
  • 生产企业内销和出口
  • 个人独资企业个人所得税税率
  • 工资分配率的计算公式
  • 接受捐赠的材料会计分录怎么写
  • 汇算清缴期间费用社保填哪里
  • 电子商务交易成本
  • 境外增值税代扣代缴
  • 员工午餐补贴可以入福利费吗?
  • 旅行社税收
  • 稽查查补税款怎么计算企业所得税
  • 公司付电费发票怎么做账
  • 产值税收是什么意思
  • 如何把两个人的照片合在一起
  • 简易计税分包抵减
  • 采用销售额比率法预测对外筹资需要量时
  • 出口企业增值税怎么算
  • 迷迭香的养殖方法
  • thinkphp i方法
  • php编程技术
  • 混合筹资的定义
  • Laravel中七个非常有用但很少人知道的Carbon方法
  • ICCV, ECCV, CVPR,IEEE的关系
  • 非货币性资产交换和债务重组的区别
  • 金蝶软件可以自学吗
  • 直连路由,静态路由
  • laravel日志管理系统
  • 收到预付购货款
  • 发票作废发票怎么处理
  • 职工福利费的范围有哪些
  • 稿酬的支付方式
  • 其他权益工具投资是金融资产吗
  • 其他应收款借贷方表示什么意思
  • python repeat函数
  • jsp连接数据库的步骤
  • mysql乱码产生原因
  • 广告公司的一般纳税人税率是多少
  • 资产负债表季报是累计三个月数据吗
  • 什么是企业会计确认计量和报告的空间范围
  • 外企可以申请高新技术
  • mysql三种安装方式
  • 购房补贴退契税多久到账
  • 上月多出来的薪资怎么算
  • 外经证预缴税款必须去外地交税吗
  • 收到国税退款的分录
  • 金融工具减值准则
  • 买别人的银行卡是啥罪
  • 会计怎么做工资单
  • window10怎么window7
  • windows任务管理器命令
  • 和查看已连接的wifi密码
  • 微软推送win10更新 蓝牙
  • centos 安装源设置出错
  • windows开机显示正在清理
  • linux播放mp3命令
  • win10系统自带的浏览器叫什么
  • linux启动cron定时任务
  • chrome heat
  • 编写批处理
  • 技术总结2000字
  • jquery写下拉框
  • python如何搭建环境
  • javascript post语法
  • python的了解
  • 河南个人医保缴费查询
  • 农用三轮车免征增值税文件
  • 建筑工程合同首付款
  • 税务核查主要核算内容
  • 2018年北京个人所得税查询
  • 宣传中常用的效应包括
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设