Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
可能很多同學(xué)還不知道 Farm , 先給大家介紹一下, Farm 是一個(gè)基于 Rust 的 Web 構(gòu)建工具, 類(lèi)似 webpack 和 vite,但更快。 Farm 用 resolve, load, transform 把所有的 asset (js/jsx/ts/tsx、css/sass/less、html、靜態(tài)資源、json 等),并將它們打包成一系列可部署文件。 Farm 作為一個(gè)速度極快的構(gòu)建工具,可幫助您更快的構(gòu)建出 web / nodejs 應(yīng)用程序。
接下來(lái)就進(jìn)入正題, 那么如何從已有的 vite 項(xiàng)目遷移到 Farm 呢 ?
從 vite 遷移到 farm 其實(shí)非常簡(jiǎn)單, 因?yàn)?farm 內(nèi)置了對(duì) vite 插件的兼容, 所以您只需要做的是將 vite.config.ts 轉(zhuǎn)換成 farm.config.js。
但是需要注意的是
我們先從基礎(chǔ)項(xiàng)目來(lái)體會(huì)一下從 vite 遷移到 Farm 有多簡(jiǎn)單
首先還是我們熟悉的創(chuàng)建 vite 項(xiàng)目
pnpm create vite
我們選一個(gè) Vue 項(xiàng)目模版, 創(chuàng)建好項(xiàng)目之后, 我們的 vite.config.ts 應(yīng)該是這樣的
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
})
那么把大象放進(jìn)冰箱一共需要三步
pnpm install @farmfe/core @farmfe/cli -D
import { defineConfig } from '@farmfe/core'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
vitePlugins: [vue()],
})
然后我們?cè)诳刂婆_(tái)執(zhí)行 npx farm start 控制臺(tái)就可以看到以下命令
執(zhí)行構(gòu)建命令 npx farm build
這樣就大功告成啦, 是不是非常簡(jiǎn)單。
接下來(lái)我們來(lái)遷移一個(gè)比較復(fù)雜的項(xiàng)目, vue-pure-admin 是一個(gè)全面ESM+Vue3+Vite+Element-Plus+TypeScript 編寫(xiě)的一款后臺(tái)管理系統(tǒng), 并且模塊數(shù)量算是比較大, 那么我們使用 Farm 來(lái)遷移這個(gè)項(xiàng)目, 來(lái)進(jìn)一步體現(xiàn)出 Farm 的優(yōu)勢(shì). 以及遷移的成本到底有多低
首先我們先克隆一下 pure-admin 的倉(cāng)庫(kù)代碼, 然后查看一下項(xiàng)目的 vite 配置文件, 并提示出遷移所需要修改的地方
import { getPluginsList } from "./build/plugins";
import { include, exclude } from "./build/optimize";
import { type UserConfigExport, type ConfigEnv, loadEnv } from "vite";
import {
root,
alias,
warpperEnv,
pathResolve,
__APP_INFO__
} from "./build/utils";
export default ({ mode }: ConfigEnv): UserConfigExport=> {
const { VITE_CDN, VITE_PORT, VITE_COMPRESSION, VITE_PUBLIC_PATH }=warpperEnv(loadEnv(mode, root));
return {
base: VITE_PUBLIC_PATH,
root,
resolve: {
alias
},
// 服務(wù)端渲染
server: {
// 端口號(hào)
port: VITE_PORT,
host: "0.0.0.0",
// 預(yù)熱文件以提前轉(zhuǎn)換和緩存結(jié)果,降低啟動(dòng)期間的初始頁(yè)面加載時(shí)長(zhǎng)并防止轉(zhuǎn)換瀑布
warmup: {
clientFiles: ["./index.html", "./src/{views,components}/*"]
}
},
plugins: getPluginsList(VITE_CDN, VITE_COMPRESSION),
// https://cn.vitejs.dev/config/dep-optimization-options.html#dep-optimization-options
optimizeDeps: {
include,
exclude
},
build: {
// https://cn.vitejs.dev/guide/build.html#browser-compatibility
target: "es2015",
sourcemap: false,
// 消除打包大小超過(guò)500kb警告
chunkSizeWarningLimit: 4000,
rollupOptions: {
input: {
index: pathResolve("./index.html", import.meta.url)
},
// 靜態(tài)資源分類(lèi)打包
output: {
chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js",
assetFileNames: "static/[ext]/[name]-[hash].[ext]"
}
}
},
define: {
__INTLIFY_PROD_DEVTOOLS__: false,
__APP_INFO__: JSON.stringify(__APP_INFO__)
}
};
};
farm 配置基本平替 vite 配置, 我們?cè)賮?lái)看一下遷移到 farm 所需要修改的配置文件,由于對(duì) css 的處理 farm 和 vite 的處理方向上的差異,所以我們只需要把一些 css 的插件配置替換成 farm 的插件, 其他的 vite 插件完全可以復(fù)用
import { getPluginsList } from "./build/plugins";
import { type UserConfigExport, type ConfigEnv, loadEnv } from "@farmfe/core";
import { root, alias, warpperEnv, __APP_INFO__ } from "./build/utils";
import postcss from "@farmfe/js-plugin-postcss";
import sass from "@farmfe/js-plugin-sass";
export default ({ mode }: ConfigEnv): UserConfigExport=> {
const { VITE_CDN, VITE_PORT, VITE_COMPRESSION, VITE_PUBLIC_PATH }=warpperEnv(loadEnv(mode, root)[0]);
return {
compilation: {
output: {
publicPath: VITE_PUBLIC_PATH,
targetEnv: "browser-es2015",
filename: "static/[ext]/[name]-[hash].[ext]",
assetsFilename: "static/[ext]/[name]-[hash].[ext]"
},
resolve: {
alias
},
script: {
plugins: [
{
name: "@swc/plugin-remove-console",
options: {
exclude: ["error"]
},
filters: {
moduleTypes: ["js", "ts", "jsx", "tsx"]
}
}
]
},
externalNodeBuiltins: false,
define: {
__INTLIFY_PROD_DEVTOOLS__: false,
__APP_INFO__: process.env.FARM_FE
? __APP_INFO__
: JSON.stringify(__APP_INFO__)
}
},
root,
// 服務(wù)端渲染
server: {
// open: true,
port: VITE_PORT
},
plugins: [
sass({
legacy: true
}),
postcss(),
{
name: "remove-css-filter-plugin",
priority: 0,
transform: {
filters: {
resolvedPaths: ["element-plus/dist/index.css"]
},
async executor({ content }) {
return {
content: content.replace(/filter:\s*alpha\(opacity=0\);/g, "")
};
}
}
}
],
vitePlugins: getPluginsList(VITE_CDN, VITE_COMPRESSION)
};
};
我們可以看到 vite 插件完全復(fù)用, 需要修改的地方僅僅是一些編譯輸出的屬性, 整體最大的修改點(diǎn)只有這些,我在 vue-pure-admin 項(xiàng)目提了一個(gè) pr, 還有一些設(shè)計(jì)差異的小細(xì)節(jié)大家可以在這里 查看 盡管從 Vite 遷移到 Farm 需要進(jìn)行一些調(diào)整和適配,但是這個(gè)過(guò)程并不復(fù)雜,而且可以通過(guò)優(yōu)化提升項(xiàng)目的性能和開(kāi)發(fā)效率。因?yàn)榇_實(shí)遷移很簡(jiǎn)單, 所以本篇文章只是簡(jiǎn)單的介紹一下 Farm 目前的可用度,隨著 Farm 的不斷發(fā)展和完善,相信它會(huì)成為更多項(xiàng)目的首選構(gòu)建工具。
注:因?yàn)?vite 對(duì)于源代碼是請(qǐng)求時(shí)編譯,所以此處加上了 “項(xiàng)目可訪(fǎng)問(wèn)時(shí)間”(即 “熱啟動(dòng)時(shí)間” + “頁(yè)面加載時(shí)間”),作為另一個(gè)指標(biāo)來(lái)綜合對(duì)比性能。所以 Farm 在熱啟動(dòng)比 vite 快 5 倍左右
farm 已經(jīng)具有了 所有開(kāi)發(fā)調(diào)試 發(fā)布 也有很大的提升空間
Farm 開(kāi)源已經(jīng)一年多了, 也已經(jīng)正式的發(fā)布了 1.0 版本, 已經(jīng)達(dá)到了生產(chǎn)可用的狀態(tài), 不僅僅是從 vite 中遷移, 在 webpack 中遷移, 團(tuán)隊(duì)中也做了非常多的嘗試, 遷移成本都很低, Farm 下一步計(jì)劃基于 Farm 打造出下一代 SSR 框架, 也希望可以有更多的同學(xué)參與進(jìn)來(lái), 共同學(xué)習(xí)進(jìn)步。
未來(lái),我們將繼續(xù)撰寫(xiě)更多的文章,深入介紹 Farm 的各項(xiàng)功能以及特性和原理解析,幫助大家更好地理解和使用下一代的構(gòu)建工具,可以對(duì)前端工程化以及代碼解析與編譯的原理理解之后, 可以更加深入地了解現(xiàn)代前端開(kāi)發(fā)的核心概念和技術(shù),并掌握構(gòu)建高效、穩(wěn)定的前端項(xiàng)目的關(guān)鍵技能。讓我們共同期待未來(lái)的探索和發(fā)現(xiàn),共同探討前端技術(shù)的前沿話(huà)題,為構(gòu)建更加美好的 Web 世界貢獻(xiàn)一份力量。
鏈接:https://juejin.cn/post/7352837711339814963
迎搜索公眾號(hào):白帽子左一
每天分享更多黑客技能,工具及體系化視頻教程(免費(fèi)領(lǐng))
來(lái)源:HACK學(xué)習(xí)呀
一直找不到目標(biāo)站點(diǎn),昨天下午收到的一條微信之后突然有了目標(biāo)
還是老規(guī)則 下載了APP 這里提示下注意事項(xiàng)
因?yàn)檫@種APP是自動(dòng)采用微信賬號(hào)登錄 且蘋(píng)果手機(jī)登錄前需要申請(qǐng)數(shù)據(jù)網(wǎng)絡(luò)權(quán)限
所以在進(jìn)行抓包前 ,需要先點(diǎn)開(kāi)APP給予數(shù)據(jù)網(wǎng)絡(luò)權(quán)限并提前登錄微信賬號(hào)(設(shè)置代理之后無(wú)法登錄微信
進(jìn)入APP后、 首先對(duì)APP內(nèi)部通過(guò)http請(qǐng)求獲取或得到數(shù)據(jù)的接口進(jìn)行了測(cè)試, 也測(cè)試得到APP走h(yuǎn)ttp請(qǐng)求的IP為 ,阿里云服務(wù)器IP地址
注意事項(xiàng) 碰到阿里云服務(wù)器(不要進(jìn)行端口掃描,不要進(jìn)行網(wǎng)頁(yè)路徑探測(cè))
因?yàn)檫@兩點(diǎn)都會(huì)讓阿里云封你的IP 首先對(duì)反饋接口進(jìn)行了抓包 丟入了XSS
丟入xss 之后 考慮到這個(gè)APP并沒(méi)有什么可以入手的點(diǎn)
(本人比較菜,沒(méi)辦法在這上面找到突破口)
于是注意到這個(gè)APP有掛載的官網(wǎng),果斷從官網(wǎng)開(kāi)始入手
首先找到了部分代理登錄的后臺(tái),進(jìn)入了登錄界面,因?yàn)橛袃蓚€(gè)登錄界面 一個(gè)是http 并且無(wú)驗(yàn)證碼
一個(gè)是https 有驗(yàn)證碼 首先從http無(wú)驗(yàn)證碼口開(kāi)始爆破密碼
https://jingyan.baidu.com/article/200957619c8739cb0721b4ff.html
Burp爆破網(wǎng)站后臺(tái)賬號(hào)密碼步驟
成功的登錄了后臺(tái),發(fā)現(xiàn)后臺(tái)并沒(méi)有什么其他功能 只是能查看個(gè)人的代理及充值返利情況
在未找到直接能getshell的點(diǎn), 首先對(duì)網(wǎng)站后臺(tái)進(jìn)行了抓包, 查看后臺(tái)中部分搜索功能是否存在SQL注入,其次查看后臺(tái)是否存在邏輯漏
可以確定的點(diǎn)如下(網(wǎng)站后臺(tái)未存在有SQL注入,數(shù)據(jù)庫(kù)不進(jìn)行報(bào)錯(cuò),對(duì)網(wǎng)站進(jìn)行掃描并未封IP
IP地址為武漢,極有可能是源IP地址,接著繼續(xù)尋找網(wǎng)站的邏輯漏洞
當(dāng)咱們對(duì)myuser.php 進(jìn)行訪(fǎng)問(wèn)時(shí) 服務(wù)器緩存的cookie 信息為以上圖片內(nèi)
aliyungf_tc 為無(wú)效數(shù)據(jù) 可無(wú)視不計(jì)算
user_name 為賬號(hào)信息 user_id為服務(wù)器uid值 user_level為用戶(hù)等級(jí)
嘗試修改賬號(hào)信息為123456789 數(shù)據(jù)并未發(fā)生改變
嘗試修改uid值 數(shù)據(jù)發(fā)生改變
嘗試修改用戶(hù)等級(jí) 未發(fā)生改變
于是得到uid 值為判斷用戶(hù)的標(biāo)準(zhǔn)
接下來(lái) 就找我親愛(ài)的丁哥寫(xiě)了套爬蟲(chóng) (用戶(hù)uid值為循環(huán)上升,爬取頁(yè)面內(nèi)容 得到網(wǎng)站總用戶(hù)量為1萬(wàn)五千人)
之前咱們提到還有一個(gè)https的后臺(tái)
有驗(yàn)證碼機(jī)制
有驗(yàn)證碼機(jī)制進(jìn)行爆破成功率可能并不是很高 嘗試進(jìn)行找回密碼功能
修改uid值為空試試
點(diǎn)擊確認(rèn)提交 直接來(lái)到了修改密碼的頁(yè)面
https://qy.xxxxxxx.com/user_goback_password.php?uid=
再進(jìn)行uid補(bǔ)全為test用戶(hù)uid=11000 輸入更改的新密碼 更改成功
成功進(jìn)入后臺(tái) 截止到目前為止
(拿到了網(wǎng)站全部用戶(hù)的個(gè)人信息,拿到了充值游戲幣的權(quán)限)
順便解釋下為什么能更改成功test用戶(hù)的密碼
當(dāng)user_goback_quan.php?uid=11000 修改為uid=空時(shí)
數(shù)據(jù)庫(kù)查詢(xún)不到用戶(hù) 那么對(duì)應(yīng)的答案也是查詢(xún)不到 為空的
更改密碼在數(shù)據(jù)庫(kù)判斷中 問(wèn)題=答案(正確) ----- 更改成功
當(dāng)問(wèn)題不存在 答案不存在的情況下 問(wèn)題=答案 跳轉(zhuǎn)到更改密碼界面 — 更改uid值為test用戶(hù)uid=====成功更改test用戶(hù)密碼
// 在已經(jīng)創(chuàng)建好的項(xiàng)目中安裝插件
vue add element
// 安裝過(guò)程中的選項(xiàng)
? Successfully installed plugin: vue-cli-plugin-element
? How do you want to import Element? Fully import
? Do you wish to overwrite Element's SCSS variables? No
? Choose the locale you want to load zh-CN
npm run serve
// 運(yùn)行結(jié)果
DONE Compiled successfully in 6537ms 22:40:55
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.1.9:8080/
vue add router
? Installing @vue/cli-plugin-router...
+ @vue/cli-plugin-router@4.4.4
updated 1 package in 16.079s
42 packages are looking for funding
run `npm fund` for details
? Successfully installed plugin: @vue/cli-plugin-router
? Use history mode for router? (Requires proper server setup for index
fallback in production) No `N`
// 1.根據(jù)element Container 布局容器創(chuàng)建主界面
<template>
</template>
<script>
export default {
}
</script>
<style>
</style>
// 2.修改router下index.js
import Main from '../views/Main.vue'
{
path: '/',
name: 'main',
component: Main
}
// 3.簡(jiǎn)化App.vue 只保留router-view
<div id="app">
<router-view/>
</div>
// 4.去除App.vue 中樣式,初始化樣式表 margin: 0;padding: 0;
// 5.修改Main.vue 中高度樣式表style="height: 100vh;"
//保留基本結(jié)構(gòu)
<template>
<el-container style="height: 100vh;">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>導(dǎo)航一</template>
<el-menu-item index="1-1">選項(xiàng)1</el-menu-item>
<el-menu-item index="1-2">選項(xiàng)2</el-menu-item>
<el-menu-item index="1-3">選項(xiàng)3</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>刪除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</template>
<style>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
<script>
export default {
data() {
const item={
date: '2020-08-08',
name: '墨客moke',
address: '青海省西寧市'
};
return {
tableData: Array(20).fill(item)
}
}
};
</script>
// 管理后臺(tái)客戶(hù)端分類(lèi)列表創(chuàng)建
// Main.vue
// 1:新建分類(lèi)、分類(lèi)列表
// 2:添加 router 屬性
// 3:導(dǎo)航菜單添加路由
<el-menu router :default-openeds="['1']"> <!-- 導(dǎo)航菜單收縮 --> <!-- router屬性 -->
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>內(nèi)容管理</template>
<el-menu-item-group>
<template slot="title">分類(lèi)</template>
<el-menu-item index="/categories/create">新建分類(lèi)</el-menu-item>
<el-menu-item index="/categories/list">分類(lèi)列表</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
為Main.vue
新建CategoriesEdit子組件
// 1.CategoriesEdit.vue
// 2.添加Main子路由
// 3.請(qǐng)求遠(yuǎn)程數(shù)據(jù)接口
// 安裝插件
F:\client\node-vue-moba\admin>cnpm i axios
√ Installed 1 packages
√ Linked 3 latest versions
√ Run 0 scripts
√ All packages installed (4 packages installed from npm registry, used
593ms(network 587ms), speed 26.3kB/s, json 4(15.44kB), tarball 0B)
// 配置使用
// http.js
import axios from 'axios'
const http=axios.create({
baseURL : 'http://localhost:3000/admin/api'
})
export default http
// main.js 創(chuàng)建axios實(shí)例
import http from './http'
Vue.prototype.$http=http
查看相關(guān)內(nèi)容見(jiàn) 0x04CRUD接口開(kāi)發(fā)
<template>
<div class="about">
<h1>{{id ? '編輯' : '新建'}}分類(lèi)</h1>
<el-form label-width="120px" @submit.native.prevent="save">
<el-form-item label="名稱(chēng)">
<el-input v-model="model.name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props:{
id:{}
},
data(){
return {
model:{}
}
},
methods:{
async save(){
// 列表新建和編輯數(shù)據(jù)更新
if (this.id) {
await this.$http.put(`categories/${this.id}`,this.model)
} else {
await this.$http.post('categories',this.model)
}
// 跳轉(zhuǎn)至分類(lèi)列表
this.$router.push('/categories/list')
this.$message({
type: 'sucess',
message: '保存成功'
})
},
// 分類(lèi)編輯1:獲取分類(lèi)數(shù)據(jù)
// 分類(lèi)編輯2:修改后更新數(shù)據(jù)
async fetch(){
const res=await this.$http.get(`categories/${this.id}`)
this.model=res.data
}
},
created(){
this.id && this.fetch()
}
}
</script>
<style>
</style>
<template>
<div class="about">
<h1>分類(lèi)列表</h1>
<el-table :data="items">
<el-table-column prop="_id" label="ID" width="245"></el-table-column>
<el-table-column prop="name" label="分類(lèi)名稱(chēng)"></el-table-column>
<el-table-column fixed="right" label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" size="small" @click="$router.push(`/categories/edit/${scope.row._id}`)">編輯</el-button>
<el-button type="text" size="small" @click="remove(scope.row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data(){
return {
items:[]
}
},
methods:{
async fetch(){
const res=await this.$http.get('categories')
this.items=res.data
},
async remove(row){
this.$confirm(`是否確定刪除${row.name}?`, '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(async ()=> {
await this.$http.delete(`categories/${row._id}`),
this.$message({
type: 'success',
message: '刪除成功!'
});
this.fetch()
})
}
},
created(){
this.fetch()
}
}
</script>
<style>
</style>
感謝閱讀,歡迎交流。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。