欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

JavaScript怎么實(shí)現(xiàn)前后端分離

本篇內(nèi)容介紹了“JavaScript怎么實(shí)現(xiàn)前后端分離”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)為客戶提供專業(yè)的成都網(wǎng)站制作、做網(wǎng)站、程序、域名、空間一條龍服務(wù),提供基于WEB的系統(tǒng)開(kāi)發(fā). 服務(wù)項(xiàng)目涵蓋了網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站程序開(kāi)發(fā)、WEB系統(tǒng)開(kāi)發(fā)、微信二次開(kāi)發(fā)、手機(jī)網(wǎng)站制作等網(wǎng)站方面業(yè)務(wù)。

前后端分離案例

現(xiàn)在把自己當(dāng)成是前端,要開(kāi)發(fā)一個(gè)前后分離的簡(jiǎn)單頁(yè)面,用于展示學(xué)生信息列表

第一步

編寫一個(gè)用于展示表格的靜態(tài)頁(yè)面

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

    </head>
    <body>
        <table id="tab" border="1">
            <tr>
                <th>編號(hào)</th>
                <th>名字</th>
                <th>年齡</th>
                <th>性別</th>
            </tr>
        </table>
        <button onclick="req()">請(qǐng)求數(shù)據(jù)</button>
        <img id="img" />
    </body>
</html>

不啟動(dòng)tomcat直接在編輯器中打開(kāi)即可訪問(wèn),此時(shí)他就是一個(gè)靜態(tài)網(wǎng)頁(yè),而我們的編輯器就是一個(gè)HTTP服務(wù)器,可以響應(yīng)靜態(tài)網(wǎng)頁(yè)

第二步

引入jquery使得ajax編寫更方便

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

第三步

編寫ajax,向服務(wù)器發(fā)送請(qǐng)求

第四步

將數(shù)據(jù)展示到頁(yè)面上

<!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>編號(hào)</th>
                <th>名字</th>
                <th>年齡</th>
                <th>性別</th>
            </tr>
        </table>
        <button onclick="req()">請(qǐng)求數(shù)據(jù)</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>

現(xiàn)在身份切換回后端開(kāi)發(fā)用于獲取表格數(shù)據(jù)的接口

  1. 創(chuàng)建web項(xiàng)目

  2. 創(chuàng)建Servlet

  3. 引入fastjson

  4. 創(chuàng)建一個(gè)bean類

  5. 創(chuàng)建一堆bean放入列表中

  6. 將列表轉(zhuǎn)為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);
    }
}

啟動(dòng)服務(wù),測(cè)試訪問(wèn),會(huì)發(fā)現(xiàn)頁(yè)面上沒(méi)有顯示服務(wù)器返回的結(jié)果&hellip;.

跨越問(wèn)題

打開(kāi)瀏覽器檢查頁(yè)面會(huì)發(fā)現(xiàn)沒(méi)有輸出服務(wù)器返回的消息而是,出現(xiàn)了一個(gè)錯(cuò)誤信息,這就是前后端分離最常見(jiàn)的跨越問(wèn)題

什么是跨域

跨越問(wèn)題之所以產(chǎn)生是因?yàn)闉g覽器都遵循了同源策略

同源策略:

同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能會(huì)受到影響。可以說(shuō)Web是構(gòu)建在同源策略基礎(chǔ)之上的,瀏覽器只是針對(duì)同源策略的一種實(shí)現(xiàn)。

同源策略是瀏覽器的行為,是為了保護(hù)本地?cái)?shù)據(jù)不被JavaScript代碼獲取回來(lái)的數(shù)據(jù)污染,瀏覽器會(huì)先發(fā)送OPTION請(qǐng)求進(jìn)行預(yù)檢查,判斷服務(wù)器是否允許跨域,如果允許才發(fā)送真正的請(qǐng)求,否則拋出異常。

簡(jiǎn)單的說(shuō):

同源策略是瀏覽器的核心安全機(jī)制,其不允許在頁(yè)面中解析執(zhí)行來(lái)自其他服務(wù)器數(shù)據(jù)

如何判斷是否跨域

當(dāng)一個(gè)請(qǐng)求url的協(xié)議、域名、端口三者之間任意一個(gè)與當(dāng)前頁(yè)面url不同即為跨域

同源限制:
  1. 無(wú)法讀取非同源網(wǎng)頁(yè)的 Cookie、LocalStorage 和 IndexedDB

  2. 無(wú)法向非同源地址發(fā)送 AJAX 請(qǐng)求

什么時(shí)候產(chǎn)生跨域問(wèn)題:

瀏覽器在解析執(zhí)行一個(gè)網(wǎng)頁(yè)時(shí),如果頁(yè)面中的js代碼請(qǐng)求了另一個(gè)非同源的資源,則會(huì)產(chǎn)生跨越問(wèn)題

而瀏覽器直接跳轉(zhuǎn)另一個(gè)非同源的地址時(shí)不會(huì)有跨域問(wèn)題

解決跨越問(wèn)題

既然禁止跨域問(wèn)題是瀏覽器的行為,那么只需要設(shè)置瀏覽器允許解析跨域請(qǐng)求的數(shù)據(jù)即可,但是這個(gè)設(shè)置必須放在服務(wù)器端,由服務(wù)器端來(lái)判斷對(duì)方是否可信任

在響應(yīng)頭中添加一個(gè)字段,告訴瀏覽器,某個(gè)服務(wù)器是可信的

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

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

其他相關(guān)設(shè)置

//指定允許其他域名訪問(wèn)
'Access-Control-Allow-Origin:http://XXX.XXX.XXX'//一般用法(*,指定域,動(dòng)態(tài)設(shè)置),注意*不允許攜帶認(rèn)證頭和cookies
//預(yù)檢查間隔時(shí)間
'Access-Control-Max-Age: 1800'
//允許的請(qǐng)求類型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//列出必須攜帶的字段
'Access-Control-Allow-Headers:x-requested-with,content-type'

解決了跨越問(wèn)題后再來(lái)完善上面的案例

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 {
        //允許來(lái)自任何主機(jī)的跨越訪問(wèn)
        response.setHeader("Access-Control-Allow-Origin","*");
                //設(shè)置響應(yīng)類型為json數(shù)據(jù)
        response.setContentType("application/json;charset=utf-8");

        //學(xué)生信息
        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>編號(hào)</th>
                <th>名字</th>
                <th>年齡</th>
                <th>性別</th>
            </tr>
        </table>
        <button onclick="req()">請(qǐng)求數(shù)據(jù)</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>

一個(gè)簡(jiǎn)單的前后端分離項(xiàng)目就搞定了

補(bǔ)充:cookie跨域

默認(rèn)情況下cookie是不允許跨域傳輸?shù)?可以通過(guò)以下方式來(lái)解決

第一步

瀏覽器端設(shè)置允許cookie跨域

第二步

服務(wù)器端在響應(yīng)中添加字段,說(shuō)明允許cookie跨域

該值只能是true,為false無(wú)效,默認(rèn)為false

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

狀態(tài)保持問(wèn)題

在傳統(tǒng)的項(xiàng)目中我們利用,session+cookie來(lái)保持用戶的登錄狀態(tài),但這在前后端分離項(xiàng)目中出現(xiàn)了問(wèn)題;

sessionid是使用cookie存儲(chǔ)在客戶端的,而cookie遵守同源策略,只在同源的請(qǐng)求中有效,這就導(dǎo)致了問(wèn)題出現(xiàn):

前后端分離后,session+cookie的問(wèn)題

  • 前后端分離后靜態(tài)資源完全可能(而且經(jīng)常....)部署到另一個(gè)域下,導(dǎo)致cookie失效,例如這樣:

在www.baidu.com中設(shè)置的cookie是不會(huì)自動(dòng)發(fā)送到cloud.baodu.comde

雖然我們可以在cookie中指定domain來(lái)解決,但是cookie必須針對(duì)性的設(shè)置作用域

這對(duì)于有多個(gè)不同域要共享cookie時(shí),可操作性差,難以維護(hù)

  • 上述問(wèn)題出現(xiàn)在前后端分離的web項(xiàng)目中,對(duì)于前后端分離的原生CS結(jié)構(gòu)項(xiàng)目而言,很多客戶端默認(rèn)是不處理session和cookie的,需要進(jìn)行相應(yīng)的設(shè)置

  • 在分布式或集群的項(xiàng)目中,共享session和cookie也是一大問(wèn)題,必須引入第三方來(lái)完成session的存儲(chǔ)和共享(也可通過(guò)中間層做cookie轉(zhuǎn)發(fā)如Nginx.Node.js),這也是傳統(tǒng)單體服務(wù)無(wú)法支持分布式和集群的問(wèn)題所在

正因?yàn)橛羞@些問(wèn)題,導(dǎo)致session+cookie的方式在某些項(xiàng)目中使用起來(lái)變得很麻煩,這時(shí)候就需要一種新的狀態(tài)維持的方式;

JWT

JWT全稱(json WEB token),是基于json數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)驗(yàn)證方式,其本質(zhì)是對(duì)json數(shù)據(jù)進(jìn)行加密后產(chǎn)生的字符串

JWT的亮點(diǎn):

  • 安全

  • 穩(wěn)定

  • 易用

  • 支持 JSON

JWT是如何做的?

回顧,之所以使用session和cookie是因?yàn)镠TTP的無(wú)狀態(tài)性質(zhì),導(dǎo)致服務(wù)器無(wú)法識(shí)別多次請(qǐng)求是否來(lái)自同一個(gè)用戶

JWT可以對(duì)用戶信息進(jìn)行加密生成一個(gè)字符串,下發(fā)到客戶端,客戶端在后續(xù)請(qǐng)求中攜帶該字符串,服務(wù)器解析后取出用戶信息,從而完成用戶身份的識(shí)別,如下圖:

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

JWT的數(shù)據(jù)結(jié)構(gòu)

JWT是一個(gè)很長(zhǎng)的字符串,分為成三個(gè)部分,中間用點(diǎn).隔開(kāi)注意; JWT 內(nèi)部是沒(méi)有換行的,這里只是為了便于展示,將它寫成了幾行。

三個(gè)組成部分如下:

  • Header(頭部)

  • Payload(負(fù)載)

  • Signature(簽名)

Header

Header 部分是一個(gè) JSON 對(duì)象,描述 JWT 的元數(shù)據(jù),例如簽名算法等,像下面這樣:

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

alg屬性表示簽名的算法,默認(rèn)是 HMAC SHA256;

typ屬性表示這個(gè)令牌(token)的類型統(tǒng)一寫為JWT

最后使用base64URL算法轉(zhuǎn)換為字符串;

Payload

Payload 部分也是一個(gè) JSON 對(duì)象,用來(lái)存放真正需要傳遞的數(shù)據(jù),JWT 規(guī)定了7個(gè)保留字段,如下:

iss (issuer):簽發(fā)人
exp (expiration time):過(guò)期時(shí)間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時(shí)間
iat (Issued At):簽發(fā)時(shí)間
jti (JWT ID):編號(hào)

服務(wù)器需要在Payload中添加用于識(shí)別用戶身份的數(shù)據(jù),也是鍵值對(duì)形式,注意不可使用保留字段,像下面這樣

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

Payload同樣使用base64URL算法轉(zhuǎn)換為字符串;

強(qiáng)調(diào):Payload數(shù)據(jù)默是不加密的,攻擊者可以通過(guò)相同的方式解析獲取

若要將用戶的關(guān)鍵數(shù)據(jù)放入其中則必須對(duì)其進(jìn)行額外的加密

Signature

部分是對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。

簽名時(shí)需要指定一個(gè)密鑰(secret)。密鑰只有服務(wù)器才知道,不能泄露給用戶。然后使用 Header 里面指定的簽名算法(默認(rèn)是 HMAC SHA256),按照下面的方式產(chǎn)生簽名。

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

最后把 Header、Payload、Signature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)".分隔返回給用戶;

總結(jié):

JWT的優(yōu)點(diǎn):

滿足REST Full的無(wú)狀態(tài)要求(為了提高系統(tǒng)的擴(kuò)展性,REST要求所有信息由請(qǐng)求端來(lái)提供,如此才使得JWT成為了分布式,集群構(gòu)架的首選方式)

在分布式,集群系統(tǒng)中使身份驗(yàn)證變得非常簡(jiǎn)單

可用于其他數(shù)據(jù)交換

合理的使用可減少數(shù)據(jù)庫(kù)查詢次數(shù)

JWT的缺點(diǎn):

對(duì)于同樣的數(shù)據(jù)JWT整體大小超過(guò)同樣數(shù)據(jù)的cookie,這會(huì)增加網(wǎng)絡(luò)負(fù)擔(dān)

服務(wù)器每次解析JWT都需要再次執(zhí)行對(duì)應(yīng)的算法,這將增加系統(tǒng)負(fù)擔(dān)

在傳統(tǒng)單體服務(wù),和WEBApp形式的前后端分離項(xiàng)目中使用JWT反而不如Session+cookie

注意事項(xiàng):
  • JWT的payload部分是不加密的,如果要放入關(guān)鍵數(shù)據(jù)則必須對(duì)其進(jìn)行加密,或是將最后的JWT整體加密

  • JWT本身用于認(rèn)證,一旦泄露,則任何人都可以使用該令牌,獲得其包含的所有權(quán)限,為了提高安全性.JWT的有效期不應(yīng)太長(zhǎng),對(duì)于一些非常權(quán)限,建議在請(qǐng)求時(shí)再次驗(yàn)證

Java中JWT的使用:

懂得原理了后我們完全可以自己來(lái)實(shí)現(xiàn),但是沒(méi)有必要,下面是目前用的較多的一個(gè)開(kāi)源庫(kù)

使用JWT的步驟總體分為三步

  1. 生成JWT

  2. 驗(yàn)證JWT

  3. 提取數(shù)據(jù)

案例:

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";

    /***
     *
     * @param secretKey 密鑰
     * @param data 用戶數(shù)據(jù)
     * @param expireTime 有效期
     * @return
     */
    public String getJWTWithHMAC256(String secretKey, HashMap<String, String> data,long expireTime){
        //指定JWT所使用的簽名算法
        Algorithm algorithm = Algorithm.HMAC256(secretKey);

        JWTCreator.Builder token = JWT.create()//創(chuàng)建token
                .withIssuer("com.kkb")//指定簽發(fā)人
                .withExpiresAt(new Date(expireTime));//有效時(shí)間
        //添加自定義數(shù)據(jù)
        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中的數(shù)據(jù)
        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);

        //驗(yàn)證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{
                //提取數(shù)據(jù)
                DecodedJWT decode = JWT.decode(token);
                System.out.println("數(shù)據(jù):"+decode.getClaim("user").asString());
                System.out.println("數(shù)據(jù):"+decode.getClaim("isAdmin").asString());
                System.out.println("簽發(fā):"+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 無(wú)效");
        }
    }
}

“JavaScript怎么實(shí)現(xiàn)前后端分離”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

網(wǎng)頁(yè)題目:JavaScript怎么實(shí)現(xiàn)前后端分離
轉(zhuǎn)載來(lái)于:http://chinadenli.net/article14/gogige.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站App設(shè)計(jì)全網(wǎng)營(yíng)銷推廣ChatGPT自適應(yīng)網(wǎng)站網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)