位置: IT常识 - 正文
前言
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',
上一篇:【深度学习】pix2pix GAN理论及代码实现与理解
下一篇:web自动化测试入门篇06 —— 元素定位进阶技巧(web自动化测试平台)
友情链接: 武汉网站建设