前端校验

This commit is contained in:
cwchen 2025-09-30 09:42:45 +08:00
parent 163c41a84b
commit 56b01565a7
7 changed files with 119 additions and 46 deletions

View File

@ -119,7 +119,10 @@ service.interceptors.request.use(
requestUrl += '?' + paramsString requestUrl += '?' + paramsString
} }
} }
const signature = generateRequestSignature(userId, timestamp, method, requestUrl, userSecret) const signature = generateRequestSignature(userId, timestamp, method, requestUrl, userSecret)
console.log(signature);
console.log(requestUrl);
config.headers['timestamp'] = timestamp config.headers['timestamp'] = timestamp
config.headers['X-Signature'] = signature config.headers['X-Signature'] = signature
} catch (error) { } catch (error) {

View File

@ -5,30 +5,38 @@
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isPathMatch(pattern, path) { export function isPathMatch(pattern, path) {
const regexPattern = pattern.replace(/\//g, '\\/').replace(/\*\*/g, '.*').replace(/\*/g, '[^\\/]*') const regexPattern = pattern
const regex = new RegExp(`^${regexPattern}$`) .replace(/\//g, '\\/')
return regex.test(path) .replace(/\*\*/g, '.*')
.replace(/\*/g, '[^\\/]*')
const regex = new RegExp(`^${regexPattern}$`)
return regex.test(path)
} }
/** /**
* 判断value字符串是否为空 * 判断value字符串是否为空
* @param {string} value * @param {string} value
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isEmpty(value) { export function isEmpty(value) {
if (value == null || value == "" || value == undefined || value == "undefined") { if (
return true value == null ||
} value == '' ||
return false value == undefined ||
value == 'undefined'
) {
return true
}
return false
} }
/** /**
* 判断url是否是http或https * 判断url是否是http或https
* @param {string} url * @param {string} url
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isHttp(url) { export function isHttp(url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
} }
/** /**
@ -37,7 +45,7 @@ export function isHttp(url) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isExternal(path) { export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path) return /^(https?:|mailto:|tel:)/.test(path)
} }
/** /**
@ -45,8 +53,8 @@ export function isExternal(path) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validUsername(str) { export function validUsername(str) {
const valid_map = ['admin', 'editor'] const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0 return valid_map.indexOf(str.trim()) >= 0
} }
/** /**
@ -54,8 +62,9 @@ export function validUsername(str) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validURL(url) { export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ const reg =
return reg.test(url) /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
} }
/** /**
@ -63,8 +72,8 @@ export function validURL(url) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validLowerCase(str) { export function validLowerCase(str) {
const reg = /^[a-z]+$/ const reg = /^[a-z]+$/
return reg.test(str) return reg.test(str)
} }
/** /**
@ -72,8 +81,8 @@ export function validLowerCase(str) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validUpperCase(str) { export function validUpperCase(str) {
const reg = /^[A-Z]+$/ const reg = /^[A-Z]+$/
return reg.test(str) return reg.test(str)
} }
/** /**
@ -81,8 +90,8 @@ export function validUpperCase(str) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validAlphabets(str) { export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/ const reg = /^[A-Za-z]+$/
return reg.test(str) return reg.test(str)
} }
/** /**
@ -90,8 +99,9 @@ export function validAlphabets(str) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function validEmail(email) { export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ const reg =
return reg.test(email) /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
} }
/** /**
@ -99,7 +109,7 @@ export function validEmail(email) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isString(str) { export function isString(str) {
return typeof str === 'string' || str instanceof String return typeof str === 'string' || str instanceof String
} }
/** /**
@ -107,10 +117,10 @@ export function isString(str) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isArray(arg) { export function isArray(arg) {
if (typeof Array.isArray === 'undefined') { if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]' return Object.prototype.toString.call(arg) === '[object Array]'
} }
return Array.isArray(arg) return Array.isArray(arg)
} }
/** /**
@ -119,19 +129,19 @@ export function isArray(arg) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isIPv4(ip) { export function isIPv4(ip) {
if (typeof ip !== 'string') return false if (typeof ip !== 'string') return false
// 基础格式校验:四段数字 // 基础格式校验:四段数字
const parts = ip.split('.') const parts = ip.split('.')
if (parts.length !== 4) return false if (parts.length !== 4) return false
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
const seg = parts[i] const seg = parts[i]
// 不能为空,必须为数字,不能有前导零(允许单个0) // 不能为空,必须为数字,不能有前导零(允许单个0)
if (seg === '' || /\D/.test(seg)) return false if (seg === '' || /\D/.test(seg)) return false
if (seg.length > 1 && seg[0] === '0') return false if (seg.length > 1 && seg[0] === '0') return false
const n = Number(seg) const n = Number(seg)
if (n < 0 || n > 255) return false if (n < 0 || n > 255) return false
} }
return true return true
} }
/** /**
@ -140,8 +150,8 @@ export function isIPv4(ip) {
* @returns {number} * @returns {number}
*/ */
function ipv4ToInt(ip) { function ipv4ToInt(ip) {
const [a, b, c, d] = ip.split('.').map(Number) const [a, b, c, d] = ip.split('.').map(Number)
return ((a << 24) >>> 0) + (b << 16) + (c << 8) + d return ((a << 24) >>> 0) + (b << 16) + (c << 8) + d
} }
/** /**
@ -151,6 +161,27 @@ function ipv4ToInt(ip) {
* @returns {Boolean} * @returns {Boolean}
*/ */
export function isIPv4RangeOrder(start, end) { export function isIPv4RangeOrder(start, end) {
if (!isIPv4(start) || !isIPv4(end)) return false if (!isIPv4(start) || !isIPv4(end)) return false
return ipv4ToInt(start) <= ipv4ToInt(end) return ipv4ToInt(start) <= ipv4ToInt(end)
} }
/**
* 统一安全校验方法
* 使用方法validSecurity(str) 返回 true/false
*/
/**
* 统一安全校验方法
* 使用方法validSecurity(str) 返回 true/false
*/
export function validSecurity(str) {
if (!str || typeof str !== 'string') {
return true;
}
// 将所有正则模式合并为一个统一的正则表达式
const securityRegex = /<script>(.*?)<\/script>|src[\r\n]*=[\r\n]*'(.*?)'|src[\r\n]*=[\r\n]*"(.*?)"|<\/script>|<script(.*?)>|eval\((.*?)\)|e-xpression\((.*?)\)|javascript:|vbscript:|onload(.*?)=|onerror(.*?)=|onclick(.*?)=|onmouseover(.*?)=|alert\((.*?)\)|<.*>|\[.*\]|\(.*\)|'.*'|".*"|%3c|%3e|%2f|%27|%22|%2b|%3b|%28|%29|%5b|%5d|@.*|!.*|%.*|\\x3c|\\x3e|\\x2f|\\x27|\\x22|data:text\/html|base64|document\.|window\.|location\.|cookie|--|\/\*.*?\*\/|#|'|"|\bselect\b|\binsert\b|\bupdate\b|\bdelete\b|\bdrop\b|\btruncate\b|\balter\b|\bcreate\b|\bexec\b|\bexecute\b|\bdeclare\b|\bxp_cmdshell\b|\bsp_\w+\b|\bchar\b|\bascii\b|\bsubstr\b|\bsubstring\b|\bconcat\b|\bmaster\b|\bsys\b|\binformation_schema\b|\bunion\b|\binto\b|\bfrom\b|\bwhere\b|\band\b|\bor\b/i;
return !securityRegex.test(str);
}

View File

@ -55,6 +55,7 @@
<script> <script>
import { getArchivalCatalogueTreeApi,delArchiveApi } from '@/api/archivesManagement/index.js' import { getArchivalCatalogueTreeApi,delArchiveApi } from '@/api/archivesManagement/index.js'
import AddTreeData from './addTreeData.vue' import AddTreeData from './addTreeData.vue'
import { validSecurity } from '@/utils/validate'
export default { export default {
name: 'LeftTree', name: 'LeftTree',
components: { AddTreeData }, components: { AddTreeData },
@ -154,6 +155,7 @@ export default {
this.selectedNodeId = data.id; this.selectedNodeId = data.id;
this.$emit('handleNodeClick', data) this.$emit('handleNodeClick', data)
}, },
// - // -
convertToVueTree(data) { convertToVueTree(data) {
if (!data || !Array.isArray(data)) { if (!data || !Array.isArray(data)) {
@ -205,6 +207,11 @@ export default {
}, },
// //
onHandleSearch() { onHandleSearch() {
//
if (this.filterText && !validSecurity(this.filterText)) {
this.$message.error('搜索内容包含非法字符,请重新输入')
return
}
this.$refs.leftTreeRef.filter(this.filterText) this.$refs.leftTreeRef.filter(this.filterText)
}, },
// //

View File

@ -56,6 +56,7 @@
<script> <script>
import { getFileManageTreeApi, delFileManageApi } from '@/api/archivesManagement/fileManager/fileManager.js' import { getFileManageTreeApi, delFileManageApi } from '@/api/archivesManagement/fileManager/fileManager.js'
import FileAddTreeData from './addTreeData.vue' import FileAddTreeData from './addTreeData.vue'
import { validSecurity } from '@/utils/validate'
export default { export default {
name: 'FileLeftTree', name: 'FileLeftTree',
components: { FileAddTreeData }, components: { FileAddTreeData },
@ -154,6 +155,7 @@ export default {
this.selectedNodeId = data.id; this.selectedNodeId = data.id;
this.$emit('handleNodeClick', data) this.$emit('handleNodeClick', data)
}, },
// - // -
convertToVueTree(data) { convertToVueTree(data) {
if (!data || !Array.isArray(data)) { if (!data || !Array.isArray(data)) {
@ -208,6 +210,11 @@ export default {
}, },
// //
onHandleSearch() { onHandleSearch() {
//
if (this.filterText && !validSecurity(this.filterText)) {
this.$message.error('搜索内容包含非法字符,请重新输入')
return
}
this.$refs.leftTreeRef.filter(this.filterText) this.$refs.leftTreeRef.filter(this.filterText)
}, },
// //

View File

@ -35,6 +35,7 @@ import _ from 'lodash'
import { import {
getFileManageTreeApi getFileManageTreeApi
} from '@/api/filesTransfer/apply' } from '@/api/filesTransfer/apply'
import { validSecurity } from '@/utils/validate'
export default { export default {
name: "FileTree", name: "FileTree",
props: ["width", "title", "rowData"], props: ["width", "title", "rowData"],
@ -121,8 +122,14 @@ export default {
// ID // ID
this.selectedNodeId = data.id; this.selectedNodeId = data.id;
}, },
// //
onHandleSearch() { onHandleSearch() {
//
if (this.filterText && !validSecurity(this.filterText)) {
this.$message.error('搜索内容包含非法字符,请重新输入')
return
}
this.$refs.leftTreeRef.filter(this.filterText) this.$refs.leftTreeRef.filter(this.filterText)
}, },
// //

View File

@ -25,6 +25,7 @@
<script> <script>
import { getLeftTreeListAPI } from '@/api/data-collect/data-set-manage' import { getLeftTreeListAPI } from '@/api/data-collect/data-set-manage'
import { validSecurity } from '@/utils/validate'
export default { export default {
name: 'LeftTree', name: 'LeftTree',
data() { data() {
@ -48,6 +49,7 @@ export default {
onHandleNodeClick(data) { onHandleNodeClick(data) {
this.$emit('handleNodeClick', data) this.$emit('handleNodeClick', data)
}, },
convertToVueTree(data) { convertToVueTree(data) {
return data.map(item => ({ return data.map(item => ({
id: item.code, id: item.code,
@ -75,6 +77,13 @@ export default {
this.displayedTreeData = JSON.parse(JSON.stringify(this.treeDataList)) this.displayedTreeData = JSON.parse(JSON.stringify(this.treeDataList))
return return
} }
//
if (!validSecurity(this.filterText)) {
this.$message.error('输入内容包含非法字符,请重新输入')
return
}
this.displayedTreeData = this.filterTreeData(this.treeDataList) this.displayedTreeData = this.filterTreeData(this.treeDataList)
}, },
// //

View File

@ -39,6 +39,7 @@
<script> <script>
import { getListDataSetAPI } from '@/api/data-collect/data-set-manage' import { getListDataSetAPI } from '@/api/data-collect/data-set-manage'
import Share from './share.vue' import Share from './share.vue'
import { validSecurity } from '@/utils/validate'
export default { export default {
name: 'RightTable', name: 'RightTable',
components: { components: {
@ -95,6 +96,7 @@ export default {
showColose() { showColose() {
this.isflag = false; this.isflag = false;
}, },
// //
onHandleQuery() { onHandleQuery() {
if (!Array.isArray(this.columns) || this.columns.length < 1) return if (!Array.isArray(this.columns) || this.columns.length < 1) return
@ -106,6 +108,13 @@ export default {
this.filteredManual = null this.filteredManual = null
return return
} }
//
if (!validSecurity(keyword)) {
this.$message.error('搜索内容包含非法字符,请重新输入')
return
}
// //
const source = Array.isArray(this.tableData) ? this.tableData : [] const source = Array.isArray(this.tableData) ? this.tableData : []
const kw = keyword.toLowerCase() const kw = keyword.toLowerCase()