前端数据展示:基于用户ID过滤数据库记录的实践与安全考量

前端数据展示:基于用户ID过滤数据库记录的实践与安全考量

本文将指导您如何在前端使用JavaScript根据当前登录用户的ID过滤并显示数据库中的特定数据行,例如只展示用户创建的招聘信息。我们将探讨客户端实现方法,并重点强调这种方式潜在的安全与性能风险,强烈建议采用后端过滤以确保数据安全和系统效率。

在现代web应用中,根据用户身份展示个性化数据是一项常见需求。例如,一个招聘平台可能需要只显示当前用户发布的职位列表,而不是所有职位。本教程将介绍如何利用javascript在客户端实现这一功能,并深入探讨其局限性与更安全的后端实现策略。

JavaScript 客户端数据过滤实现

假设我们已经通过AJAX请求从后端获取了所有招聘信息数据,并希望在前端HTML表格中仅显示由当前登录用户创建的记录。

1. 获取当前用户ID

首先,我们需要在JavaScript中获取当前登录用户的唯一标识符。这个ID可能通过多种方式提供,例如:

  • 从后端渲染的隐藏HTML元素中获取(如 zuojiankuohaophpcndiv data-ms-member=”id”>123</div>)。
  • 通过JavaScript全局变量或LocalStorage获取。
  • 通过专门的用户会话API获取。

以下代码片段演示了如何从一个带有特定属性的HTML元素中提取用户ID:

立即学习前端免费学习笔记(深入)”;

// 假设您的HTML中有一个元素,其data-ms-member="id"属性包含了当前用户的ID const currentUserIDElement = document.querySelector('[data-ms-member="id"]'); const currentUserID = currentUserIDElement ? currentUserIDElement.textContent.trim() : null;  if (!currentUserID) {     console.error("无法获取当前登录用户ID,请确保用户已登录且ID可用。");     // 如果无法获取用户ID,通常应停止后续的数据加载和显示操作     // 或者显示一个错误消息给用户 }

2. 遍历数据并应用过滤逻辑

获取到当前用户ID后,我们可以在处理从数据库获取的数据时,对每一条记录进行比较。如果记录的 createdByUserID 字段与 currentUserID 不匹配,则跳过该记录,不将其渲染到HTML表格中。

下面是修改后的JavaScript代码,包含了过滤逻辑:

$(function() {     // 假设这里已成功获取到当前登录用户的ID     const currentUserIDElement = document.querySelector('[data-ms-member="id"]');     const currentUserID = currentUserIDElement ? currentUserIDElement.textContent.trim() : null;      if (!currentUserID) {         // 如果无法获取用户ID,则停止执行后续逻辑         console.error("错误:无法获取当前登录用户ID。");         return;     }      $.getJSON('https://db-ommitted-for-privacy?tableName=JobListings&fields=company,logo,img,companyDescription,role,roleDescription,location,link,createdByUserID,dateAdded&view=AllListings', function(data) {         // 确保data.records存在且是数组         if (!data || !Array.isArray(data.records)) {             console.error("从API获取的数据格式不正确或为空。");             return;         }          $.each(data.records, function(i, { fields: f }) {             // 核心过滤逻辑:如果数据项的创建者ID与当前用户ID不匹配,则跳过当前循环迭代             // 注意:在jQuery.each中,返回 true 相当于 continue,返回 false 相当于 break。             if (currentUserID !== f.createdByUserID) {                 return true; // 跳过当前记录,继续处理下一条             }              // 构建表格行内容             var tblRow = "<tr>" +                 "<td>" +                     "<div style='padding-top: 1%; padding-bottom: 1%;'>" +                         "<div style='border: 1px solid black;'>" +                             "<button class='accordionList' style='font-size: large; outline: none;'>" +                                 "<span style='padding-top: 2.5%; padding-bottom: 3%;'>" +                                     "<img src='" + f.logo + "' height='30px'>" +                                 "</span>  <span style='padding-top: 3%; padding-bottom: 3%;'>   " +                                     f.company + "   |   " + f.role +                                 "    <span style='color: #2b2b2b;''><span class='iconify-inline' data-icon='eva:pin-outline' style='color: #2b2b2b;'></span> " + f.location +"</span></span>" +                             "</button>" +                             "<div class='panel'>" +                                 "<img src='img/jobBanner2.png' width='100%'>" +                                 "<br>" +                                 "<p style='color: #505050;'>Posted: " + f.dateCreated + "   |   Status: " + f.status + "</p>" +                                 "<h4>About this role:</h4>" +                                 "<p>" + f.roleDescription + "</p>" +                                 "<h4>About " + f.company + ":</h4>" +                                 "<p>" + f.companyDescription + "</p>" + "<br>" +                                 "<a href='pricing.html' class='button btn btn-lg btn-block btn-sm button-black' style='padding-top: 1%; padding-bottom: 1%; width: 200px;'>apply   <span class='iconify-inline' data-icon='bi:arrow-right-circle' data-width='15' style='color: white;'></span></a>" +                                 "<br>" + "</div>" +                             "</div>" +                         "</div>" +                     "</div>" +                 "</td>" +             "</tr>";             $(tblRow).appendTo("#userdata tbody");         });     }).fail(function(jqXHR, textStatus, errorThrown) {         console.error("API请求失败: " + textStatus, errorThrown);         // 可以向用户显示一个友好的错误消息     }); });

重要的注意事项:客户端过滤的局限性

尽管上述方法可以实现前端数据显示过滤,但在实际生产环境中,这种做法存在严重的安全和性能隐患,因此不建议用于处理敏感数据或大规模数据集。

前端数据展示:基于用户ID过滤数据库记录的实践与安全考量

神笔马良

神笔马良 – AI让剧本一键成片。

前端数据展示:基于用户ID过滤数据库记录的实践与安全考量144

查看详情 前端数据展示:基于用户ID过滤数据库记录的实践与安全考量

1. 安全性风险

  • 数据泄露: 客户端过滤的核心问题在于,所有数据(包括不应向当前用户显示的数据)都已从服务器传输到了用户的浏览器。恶意用户可以通过浏览器的开发者工具(如网络请求查看器)轻松拦截和检查这些原始数据,从而绕过前端的JavaScript过滤,访问到他们无权查看的信息。这对于个人隐私、商业机密等敏感数据是不可接受的。

2. 性能问题

  • 不必要的网络传输: 即使只显示少数几条记录,服务器也需要将整个数据集发送到客户端。如果数据库表包含数千甚至数百万条记录,这将导致巨大的网络带宽浪费,增加数据传输时间,严重影响页面加载速度。
  • 客户端处理负担: 浏览器需要下载、解析并遍历所有数据,即使大部分数据最终被过滤掉。这会消耗客户端的CPU和内存资源,尤其是在移动设备或性能较低的电脑上,可能导致页面卡顿、响应迟缓。

推荐的解决方案:后端过滤

为了彻底解决上述安全和性能问题,最佳实践是在服务器端进行数据过滤。这意味着在数据离开服务器之前,就根据当前用户的身份和权限进行筛选。

后端过滤的优势:

  • 数据安全: 只有经过授权的数据才会从服务器发送到客户端。未经授权的数据永远不会暴露在用户的浏览器中,从根本上杜绝了数据泄露的风险。
  • 性能优化: 服务器只查询并返回与当前用户相关的数据,显著减少了网络传输量和客户端的处理负担。这使得页面加载更快,用户体验更流畅。
  • 逻辑集中化: 数据访问控制逻辑集中在后端,更易于管理、维护和测试。前端只需负责数据的展示,无需关心数据的权限问题。

后端过滤的实现思路:

  1. 客户端请求: 前端向后端发送数据请求,通常会携带用户认证信息(如Token、Session ID)。
  2. 后端认证与授权: 后端API接收请求后,首先验证用户的身份,并根据用户ID和权限规则,确定该用户可以访问哪些数据。
  3. 数据库查询: 后端在执行数据库查询时,将用户ID作为过滤条件(例如,SELECT * FROM JobListings WHERE createdByUserID = :currentUserID)。
  4. 返回过滤后的数据: 数据库只返回符合条件的数据,后端将这些数据封装后发送给前端。

无论是使用PHP、Node.js、Python(如Django/Flask)、Java或其他后端技术栈,都应遵循这一原则。

总结

客户端JavaScript过滤虽然能快速实现数据展示的个性化需求,但其固有的安全漏洞和性能瓶颈使其不适合用于生产环境,尤其当涉及敏感数据或大量数据时。对于任何需要基于用户身份进行数据访问控制的场景,强烈建议采用后端过滤机制,以确保数据安全、提升系统性能并优化用户体验。在开发过程中,始终优先考虑数据安全,将权限控制逻辑放在服务器端执行是构建健壮可靠应用的基石。

以上就是php javascript python java jquery html js 前端 node.js json Python Java php JavaScript django flask ajax html 封装 select Session Token 标识符 全局变量 数据封装 JS 数据库 性能优化

大家都在看:

php javascript python java jquery html js 前端 node.js json Python Java php JavaScript django flask ajax html 封装 select Session Token 标识符 全局变量 数据封装 JS 数据库 性能优化

app
上一篇
下一篇