iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >JavaScript怎么实现前后端分离
  • 658
分享到

JavaScript怎么实现前后端分离

2024-04-02 19:04:59 658人浏览 薄情痞子
摘要

本篇内容介绍了“javascript怎么实现前后端分离”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 前

本篇内容介绍了“javascript怎么实现前后端分离”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

前后端分离案例

现在把自己当成是前端,要开发一个前后分离的简单页面,用于展示学生信息列表

第一步

编写一个用于展示表格的静态页面

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>

    </head>
    <body>
        <table id="tab" border="1">
            <tr>
                <th>编号</th>
                <th>名字</th>
                <th>年龄</th>
                <th>性别</th>
            </tr>
        </table>
        <button onclick="req()">请求数据</button>
        <img id="img" />
    </body>
</html>

不启动Tomcat直接在编辑器中打开即可访问,此时他就是一个静态网页,而我们的编辑器就是一个Http服务器,可以响应静态网页

第二步

引入Jquery使得ajax编写更方便

<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

第三步

编写ajax,向服务器发送请求

第四步

将数据展示到页面上

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    </head>
    <body>
        
        <table id="tab" border="1">
            <tr>
                <th>编号</th>
                <th>名字</th>
                <th>年龄</th>
                <th>性别</th>
            </tr>
        </table>
        <button onclick="req()">请求数据</button>
        <img id="img" />
    </body>
    <script>
        function req(){
            document.getElementById("img").src = "img/timg.gif";
            $.ajax({
                url:"http://localhost:8080/MyServer/getData",
                success:function(data){
                    console.log(data);
                    document.body.insertAdjacentHTML("beforeend","<h2>%</h2>".replace("%",data));
                    document.getElementById("img").src = "";    
                },
                error:function(err){
                    console.log(err);
                    document.getElementById("img").src = "";    
                }
            });
        }
    </script>
</html>

现在身份切换回后端开发用于获取表格数据的接口

  1. 创建WEB项目

  2. 创建Servlet

  3. 引入fastJSON

  4. 创建一个bean类

  5. 创建一堆bean放入列表中

  6. 将列表转为json字符串 返回给前端

Servlet代码

package com.kkb;

import java.io.IOException;

public class AServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    }
    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        String s = "{\"name\":\"jack\"}";
        response.getWriter().println(s);
    }
}

启动服务,测试访问,会发现页面上没有显示服务器返回的结果&hellip;.

跨越问题

打开浏览器检查页面会发现没有输出服务器返回的消息而是,出现了一个错误信息,这就是前后端分离最常见的跨越问题

什么是跨域

跨越问题之所以产生是因为浏览器都遵循了同源策略

同源策略:

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,浏览器会先发送OPTION请求进行预检查,判断服务器是否允许跨域,如果允许才发送真正的请求,否则抛出异常。

简单的说:

同源策略是浏览器的核心安全机制,其不允许在页面中解析执行来自其他服务器数据

如何判断是否跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

同源限制:
  1. 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

  2. 无法向非同源地址发送 AJAX 请求

什么时候产生跨域问题:

浏览器在解析执行一个网页时,如果页面中的js代码请求了另一个非同源的资源,则会产生跨越问题

而浏览器直接跳转另一个非同源的地址时不会有跨域问题

解决跨越问题

既然禁止跨域问题是浏览器的行为,那么只需要设置浏览器允许解析跨域请求的数据即可,但是这个设置必须放在服务器端,由服务器端来判断对方是否可信任

在响应头中添加一个字段,告诉浏览器,某个服务器是可信的

package com.kkb;

import java.io.IOException;

public class AServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin","*");
        String s = "{\"name\":\"jack\"}";
        response.getWriter().println(s);
    }
}

其值可以是某个或多个指定的域名,也可以是*表示信任所有地址

其他相关设置

//指定允许其他域名访问
'Access-Control-Allow-Origin:http://XXX.XXX.XXX'//一般用法(*,指定域,动态设置),注意*不允许携带认证头和cookies
//预检查间隔时间
'Access-Control-Max-Age: 1800'
//允许的请求类型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//列出必须携带的字段
'Access-Control-Allow-Headers:x-requested-with,content-type'

解决了跨越问题后再来完善上面的案例

Servlet代码:
package com.kkb;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;
import java.util.ArrayList;

public class AServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        //允许来自任何主机的跨越访问
        response.setHeader("Access-Control-Allow-Origin","*");
                //设置响应类型为json数据
        response.setContentType("application/json;charset=utf-8");

        //学生信息
        ArrayList<Student> students = new ArrayList<>();

        Student stu1 = new Student("s1","jack",20,"man");
        Student stu2 = new Student("s2","tom",22,"girl");
        Student stu3 = new Student("s3","jerry",10,"woman");
        Student stu4 = new Student("s4","scot",24,"boy");
        students.add(stu1);
        students.add(stu2);
        students.add(stu3);
        students.add(stu4);
        response.getWriter().println(JSON.toJSONString(JSON.toJSONString(students)));
    }
}
HTML代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    </head>
    <body>
        <table id="tab" border="1">
            <tr>
                <th>编号</th>
                <th>名字</th>
                <th>年龄</th>
                <th>性别</th>
            </tr>
        </table>
        <button onclick="req()">请求数据</button>
        <img id="img" />
    </body>
    <script>
        function req(){
            document.getElementById("img").src = "img/timg.gif";
            $.ajax({
                url:"http://localhost:8080/MyServer/getData",
                success:function(data){
                    data = JSON.parse(data)
                    console.log(data)
                    for (var i = 0; i < data.length; i++) { 
                        a = data[i];
                        var row = "<tr><td>id</td><td>name</td><td>age</td><td>gender</td></tr>"
                            row = row.replace("id",a.id);
                            row = row.replace("name",a.name);
                            row = row.replace("age",a.age);
                            row = row.replace("gender",a.gender);   
                            document.getElementById("tab").insertAdjacentHTML("beforeend",row);
                    }
                    document.getElementById("img").src = "";    
                },
                error:function(err){
                    console.log(err);
                    document.getElementById("img").src = "";    
                }
            });
        }
    </script>
</html>

一个简单的前后端分离项目就搞定了

补充:cookie跨域

默认情况下cookie是不允许跨域传输的.可以通过以下方式来解决

第一步

浏览器端设置允许cookie跨域

第二步

服务器端在响应中添加字段,说明允许cookie跨域

该值只能是true,为false无效,默认为false

#'Access-Control-Allow-Credentials:true'

状态保持问题

在传统的项目中我们利用,session+cookie来保持用户的登录状态,但这在前后端分离项目中出现了问题;

sessionid是使用cookie存储在客户端的,而cookie遵守同源策略,只在同源的请求中有效,这就导致了问题出现:

前后端分离后,session+cookie的问题

  • 前后端分离后静态资源完全可能(而且经常....)部署到另一个域下,导致cookie失效,例如这样:

在www.baidu.com中设置的cookie是不会自动发送到cloud.baodu.comde

虽然我们可以在cookie中指定domain来解决,但是cookie必须针对性的设置作用域

这对于有多个不同域要共享cookie时,可操作性差,难以维护

  • 上述问题出现在前后端分离的web项目中,对于前后端分离的原生CS结构项目而言,很多客户端默认是不处理session和cookie的,需要进行相应的设置

  • 分布式集群的项目中,共享session和cookie也是一大问题,必须引入第三方来完成session的存储和共享(也可通过中间层做cookie转发如Nginx.node.js),这也是传统单体服务无法支持分布式和集群的问题所在

正因为有这些问题,导致session+cookie的方式在某些项目中使用起来变得很麻烦,这时候就需要一种新的状态维持的方式;

Jwt

JWT全称(json WEB token),是基于json数据结构的数据验证方式,其本质是对json数据进行加密后产生的字符串

JWT的亮点:

  • 安全

  • 稳定

  • 易用

  • 支持 JSON

JWT是如何做的?

回顾,之所以使用session和cookie是因为HTTP的无状态性质,导致服务器无法识别多次请求是否来自同一个用户

JWT可以对用户信息进行加密生成一个字符串,下发到客户端,客户端在后续请求中携带该字符串,服务器解析后取出用户信息,从而完成用户身份的识别,如下图:

session共享和JWT在集群中的不同

JWT的数据结构

JWT是一个很长的字符串,分为成三个部分,中间用点.隔开注意; JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

三个组成部分如下:

  • Header(头部)

  • Payload(负载)

  • Signature(签名)

Header 部分是一个 JSON 对象,描述 JWT 的元数据,例如签名算法等,像下面这样:

{
  "alg": "HS256",
  "typ": "JWT"
}

alg属性表示签名的算法,默认是 HMac SHA256;

typ属性表示这个令牌(token)的类型统一写为JWT

最后使用base64URL算法转换为字符串;

Payload

Payload 部分也是一个 JSON 对象,用来存放真正需要传递的数据,JWT 规定了7个保留字段,如下:

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

服务器需要在Payload中添加用于识别用户身份的数据,也是键值对形式,注意不可使用保留字段,像下面这样

{
  "sub": "test JWT",
  "name": "jerry",
  "isadmin": true
}

Payload同样使用base64URL算法转换为字符串;

强调:Payload数据默是不加密的,攻击者可以通过相同的方式解析获取

若要将用户的关键数据放入其中则必须对其进行额外的加密

Signature

部分是对前两部分的签名,防止数据篡改。

签名时需要指定一个密钥(secret)。密钥只有服务器才知道,不能泄露给用户。然后使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的方式产生签名。

signature = HMACSHA256(base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)

最后把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点".分隔返回给用户;

总结:

JWT的优点:

满足REST Full的无状态要求(为了提高系统的扩展性,REST要求所有信息由请求端来提供,如此才使得JWT成为了分布式,集群构架的首选方式)

在分布式,集群系统中使身份验证变得非常简单

可用于其他数据交换

合理的使用可减少数据库查询次数

JWT的缺点:

对于同样的数据JWT整体大小超过同样数据的cookie,这会增加网络负担

服务器每次解析JWT都需要再次执行对应的算法,这将增加系统负担

在传统单体服务,和WEBApp形式的前后端分离项目中使用JWT反而不如Session+cookie

注意事项:
  • JWT的payload部分是不加密的,如果要放入关键数据则必须对其进行加密,或是将最后的JWT整体加密

  • JWT本身用于认证,一旦泄露,则任何人都可以使用该令牌,获得其包含的所有权限,为了提高安全性.JWT的有效期不应太长,对于一些非常权限,建议在请求时再次验证

Java中JWT的使用:

懂得原理了后我们完全可以自己来实现,但是没有必要,下面是目前用的较多的一个开源

使用JWT的步骤总体分为三步

  1. 生成JWT

  2. 验证JWT

  3. 提取数据

案例:

package com.kkb;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.alGorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class JWTTool {
    //自定义密钥
    public static final String secreTKEy = "askjdksadjkasdakjshdjkasdkAakjshdjasdjs";

    
    public String getJWTWithHMAC256(String secretKey, HashMap<String, String> data,long expireTime){
        //指定JWT所使用的签名算法
        Algorithm algorithm = Algorithm.HMAC256(secretKey);

        JWTCreator.Builder token = JWT.create()//创建token
                .withIssuer("com.kkb")//指定签发人
                .withExpiresAt(new Date(expireTime));//有效时间
        //添加自定义数据
        if (data != null){
            for (Map.Entry<String, String> a :data.entrySet()) {
                token.withClaim(a.getKey(),a.getValue());
            }
        }
        return token.sign(algorithm);
    }

    public boolean verifyTokenWithHMAC256(String token,String secretKey){
        try{
            Algorithm algorithm = Algorithm.HMAC256(secretKey);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("com.kkb")
                    .build();
            verifier.verify(token);
            return true;
        }catch (JWTVerificationException e){
            e.printStackTrace();
            return false;
        }
    }

    public static void main(String[] args) {
        JWTTool jwtTool = new JWTTool();

        //要添加到token中的数据
        HashMap<String,String> data = new HashMap<>();
        data.put("user","jerry");
        data.put("isAdmin","true");

        //有效期
        long expiresTime = new Date().getTime() + 1000 * 60 * 60;

        //生成token
        String token = jwtTool.getJWTWithHMAC256(secretKey,data,expiresTime);
        System.out.println(token);

        //验证token
        //If the token has an invalid signature or the Claim requirement is not met
        if (jwtTool.verifyTokenWithHMAC256(token,secretKey)){
            System.out.println("token 有效");
            try{
                //提取数据
                DecodedJWT decode = JWT.decode(token);
                System.out.println("数据:"+decode.getClaim("user").asString());
                System.out.println("数据:"+decode.getClaim("isAdmin").asString());
                System.out.println("签发:"+decode.getIssuer());
                System.out.println("有效期"+decode.getExpiresAt());

            }catch (JWTDecodeException e){
                //If the token has an invalid syntax or the header or payload are not JSONs,
                System.out.println("解析token失败");
            }
        }else {
            System.out.println("token 无效");
        }
    }
}

“JavaScript怎么实现前后端分离”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: JavaScript怎么实现前后端分离

本文链接: https://www.lsjlt.com/news/95602.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript怎么实现前后端分离
    本篇内容介绍了“JavaScript怎么实现前后端分离”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 前...
    99+
    2024-04-02
  • django前后端分离怎么实现
    要实现Django的前后端分离,可以使用Django Rest Framework(DRF)作为后端框架,同时使用一个前端框架(如R...
    99+
    2023-10-09
    django
  • SpringSecurity怎么实现前后端分离
    今天小编给大家分享一下SpringSecurity怎么实现前后端分离的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Sprin...
    99+
    2023-07-05
  • Sping Security前后端分离怎么实现
    本篇内容主要讲解“Sping Security前后端分离怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Sping Security前后端分离怎么实现”吧!Spring...
    99+
    2023-07-05
  • thinkphp怎么实现前后端分离验证码
    这篇文章主要介绍了thinkphp怎么实现前后端分离验证码的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇thinkphp怎么实现前后端分离验证码文章都会有所收获,下面我们一起来看看吧。一、验证码的作用在互联网时...
    99+
    2023-07-06
  • SpringSecurity如何实现前后端分离
    这篇文章主要介绍“SpringSecurity如何实现前后端分离”,在日常操作中,相信很多人在SpringSecurity如何实现前后端分离问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringSecur...
    99+
    2023-07-05
  • Springboot怎么实现前后端分离excel下载
    本篇内容介绍了“Springboot怎么实现前后端分离excel下载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Springboot前后端...
    99+
    2023-06-25
  • php前后端分离如何实现
    要实现PHP前后端分离,需要使用以下技术和方法:1. 使用前端框架:选择一个前端框架(如React、Vue.js、Angular等)...
    99+
    2023-10-09
    php
  • thinkphp怎么实现前后端分离的开发
    这篇文章主要讲解了“thinkphp怎么实现前后端分离的开发”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“thinkphp怎么实现前后端分离的开发”吧!跨域访问在前后端分离的开发中,前端通常...
    99+
    2023-07-05
  • git前后端分离怎么用
    随着前端技术的繁荣发展,前端领域出现了越来越多的框架和技术,前后端分离也成为了现阶段 web 开发的一种趋势。其中,git 的使用对于前后端分离的管理起到了至关重要的作用。本文将介绍 git 前后端分离的使用方法。一、前后端分离的基本概念前...
    99+
    2023-10-22
  • thinkPHP5前后端分离
    thinkPHP5前后端分离 环境配置并运行起thinkphp安装小皮面板安装phpstorm配置thinkPHP5将文件放入适当位置修改Nginx配置修改配置和伪静态 跨域前端 ...
    99+
    2023-10-11
    php 前端 nginx 1024程序员节
  • 前后端分离djangorestframe
    关于验证码部分,在我这篇文章里说的挺详细的了:Python高级应用(3)—— 为你的项目添加验证码   这里还是再给一个前后端分离的实例,因为极验官网给的是用session作为验证的,而我们做前后端分离的用的是token,而不是sessi...
    99+
    2023-01-30
    后端 djangorestframe
  • Springboot实现前后端分离excel下载
    目录Springboot前后端分离excel下载前后端分离Excle下载乱码问题前端请求方式 : ajax请求Springboot前后端分离excel下载 现在公司的技术栈是spri...
    99+
    2024-04-02
  • web前后端分离与前后端不分离的区别是什么
    本篇内容主要讲解“web前后端分离与前后端不分离的区别是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“web前后端分离与前后端不分离的区别是什么”吧!前后端...
    99+
    2024-04-02
  • Docker+Nginx打包部署前后端分离怎么实现
    这篇文章主要介绍“Docker+Nginx打包部署前后端分离怎么实现”,在日常操作中,相信很多人在Docker+Nginx打包部署前后端分离怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Docker+...
    99+
    2023-07-04
  • php前后端分离怎么部署
    在进行PHP前后端分离部署的过程中,一般涉及以下几个步骤:1. 前端项目构建:首先,你需要将前端项目构建为静态文件,包括HTML、C...
    99+
    2023-10-20
    php
  • 如何用php实现前端后台分离
    这篇文章主要讲解了“如何用php实现前端后台分离”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用php实现前端后台分离”吧!构建后台API接口PHP作为一种服务器端脚本语言,相比于Jav...
    99+
    2023-07-05
  • Java项目如何实现前后端分离
    今天就跟大家聊聊有关Java项目如何实现前后端分离,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。构建springboot项目我的目录结构:(结果未按标准书写,仅作说明)不管用什么ID...
    99+
    2023-05-31
    java 前后端分离 ava
  • Python+Vue实现简单的前后端分离
    准备工作 安装Node环境安装Python环境 注意:项目整个过程需要从后往前,即先数据库->后端->前端;启动流程也是先启动后端项目,再启动前端项目 完整项目地址:地址 前端 开发工具:Vis...
    99+
    2023-08-31
    python vue mysql 前后端分离
  • FastApi+Vue+LayUI如何实现前后端分离
    小编给大家分享一下FastApi+Vue+LayUI如何实现前后端分离,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言在前面的Api开发中,我们使用FastAp...
    99+
    2023-06-25
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作