背景
随着Web应用的普及和发展,前端代码越来越多地暴露在客户端环境中运行。这种开放性虽然带来了更好的用户体验,但也为恶意用户提供了可乘之机。前端 JavaScript 代码容易被查看、修改甚至替换,这使得保护前端逻辑变得尤为重要。
示例
输入验证绕过
示例代码:
<template> <div> <el-form :model="ruleForm" ref="ruleForm" :rules="rules" label-position="left" label-width="86px"> <el-row class="row-from"> <el-col class="text-left col-item"> <el-form-item label="项目成员" prop="oneName"> <el-tooltip class="item" size="medium" effect="dark" :disabled="selectNum == 0" placement="top" v-model="isShowTooltip"> <div slot="content" class="tooltip-con"> <div v-for="item in selectUserList" :key="item.userId" class="size16 team-text">{{ `${item.userName} - ${item.phone}` }}</div> <i class="el-icon-close close" @click="closeTooltip"></i> </div> <el-badge :value="selectNum" class="item" type="primary"> <el-input size="medium" v-model="ruleForm.oneName" clearable @focus="showDialog" placeholder="请选择"></el-input> </el-badge> </el-tooltip> </el-form-item> </el-col> </el-row> <el-row class="row-from"> <el-col class="text-left"> <el-button class="btn select" size="medium" @click="submit" type="primary">提交</el-button> </el-col> </el-row> </el-form> <SDialog ref="SDialog" @selectUser="selectUser"></SDialog> </div></template><script>import SDialog from '@/views/popupAndSelect/SDialog.vue';export default { name: 'show', data() { const checkOneName = (rule, value, callback) => { console.log('checkTeam::: ', value); if (!value) { callback(new Error('请选择和作社项目组名称')) } else { callback() } }; return { isShowTooltip: false, selectNum: 0, rules: { oneName: [ { required: true, message: '请选择名字', trigger: 'blur,change' }, { validator: checkOneName, trigger: 'change' } ], }, ruleForm: { nameList: [], userIds: [], oneName: "", }, selectUserList: [], } }, components: { SDialog }, methods: { showDialog() { this.$refs.SDialog.show() }, selectUser(data) { console.log('data::: ', data); // 拿到所有用户的 userName let nameList = data.map(item => item.userName); this.ruleForm.oneName = `${data[0].userName} - ${data[0].phone}`; this.selectNum = nameList.length; this.ruleForm.nameList = nameList; // 拿到所有用户的 userId this.ruleForm.userIds = data.map(item => item.userId); this.selectUserList = data; }, // 关闭 Tooltip closeTooltip() { this.isShowTooltip = false; }, // 提交表单 submit() { this.$refs.ruleForm.validate(valid => { if (valid) { this.$message({ message: '提交成功', type: 'success' }); } else { console.log('error submit!!'); return false; } }); }, }}</script>
绕过方法: 攻击者可以通过修改浏览器控制台中的代码,进行绕过验证
防范措施:
参考文档: 使用 webpack-obfuscator 进行代码混淆
css样式控制绕过
在 Vue 中使用v-show
判断的按钮
示例代码:
<template> <div> <h1>js绕过</h1> <div> <button v-show="showBtn" @click="submit">btn1</button> <button v-if="showBtn" @click="submit1">btn2</button> </div> </div></template><script>export default { name: "JsbBypass", data() { return { showBtn: false, }; }, methods: { submit(){ console.log('submit触发了::: '); }, submit1(){ console.log('submit1触发了::: '); } }};</script>
绕过方法: 攻击者可以通过修改浏览器控制台中的css属性,使按钮在页面显示出来,从而可以点击触发相应的事件
防范措施:
禁用开发者工具:虽然不推荐,但在某些情况下可以考虑禁用开发者工具。
改为 v-if
:使用 v-if
后,页面上不对存在元素。
<button v-if="showBtn" @click="submit">btn1</button>
在绑定的事件函数内部做判断
submit() { if (!this.showBtn) return; console.log('submit触发了::: ');},
使用 readonly
或者 disabled
禁用表单元素
示例代码:
<template> <div> <h1>css绕过</h1> <div> <input style="width: 200px;margin-right:15px" :disabled="isDisabled"></input> <input style="width: 200px;margin-right:15px" :readonly="isReadonly"></input> <button :disabled="isDisabled" @click="submit">btn</button> </div> </div></template><script>export default { name: "disabledBypass", data() { return { isDisabled: "disabled", isReadonly: "readonly" }; }, methods: { submit() { console.log('submit触发了::: '); }, }};</script>
绕过方法: 攻击者可以通过删除浏览器控制台标签的 css 属性,从而使得已被禁用的表单元素生效。
防范措施:
禁用开发者工具:虽然不推荐,但在某些情况下可以考虑禁用开发者工具。
服务器端验证:确保对提交的数据进行严格的验证。
按钮可以通过绑定的事件函数内部进行判断
submit() { if (this.isDisabled === 'disabled' || this.isReadonly === 'readonly') return; console.log('submit触发了::: ');},
总结
在 Web 应用开发中,前端代码的开放性为恶意用户提供了绕过验证和控制的机会。为了保障应用的安全性,应采取多方面的防护措施。首先,始终在服务器端进行严格的输入验证,确保数据的安全性和完整性。其次,合理使用 Vue 的响应式特性,如 v-if 和 v-show,并在事件处理函数中进行状态检查,防止用户通过修改浏览器控制台中的代码或 CSS 属性来绕过前端控制。此外,可以考虑对前端代码进行混淆处理,增加攻击者的破解难度。综合这些措施,可以有效提升 Web 应用的安全性。