JWT##
一种可以把token保存在cookie中的前端会话解决方案。相对于传统的session,它有效的减轻了后端的存储和随之而来的增删改查的压力。但相应的,由于是保存在前端cookie中,处于对其安全性的考量,加密/解密的过程会带来一定的服务器压力。
其构成分为三部分:
header
{ typ:"jwt", alg:"HS256" }
可以看出,头部用来保存两个信息:token的类型和其加密的算法。
claims(payload)
{
iss:"temp.com",
sub:"uid123",
exp:"123456789",
iat:"123456789",
jtd:"hiy5td656fifs85yd"
}
jwt的实体,保存了这个jwt的发布者(iss),其实就是这个站点标识;操作的对象,也称之为这个jwt的主题(sub),我在操作的时候保存的是用户id,不过鉴于其json的数据存储形式,我觉得直接保存用户对象也何尝不可(以后可以尝试一下)。既然描述的是主题,那么意味着这其中也应当填写操作的动词(究竟干了什么);这个jwt的创建时间(iat)和过期时间(exp),这个没什么好说的,但是后端的过期逻辑得注意一点,不然时间间隔太久,这一块的测试工作可能会遗漏(我就是,写了两块登陆状态的判断逻辑,结果其中一块有bug,直接导致流程来回跳转不停,一边提示未登录,一边提示已登陆);由于我是使用的jwt模块,所以未给出jtd(jwt的id)这个参数,可能模块帮助我生成了(官网上我已经找不到这个字段的说明了)。
signature
const sig = [
encode(header),
encode(claims)
].join(".");
const signature = identifiedAlg(sig + secret);
有效性验证块,一般拿前面两块的encode字段配合服务器给出的secret的标识同时加密所得,主要用于jwt的恶意篡改。
组合
三块内容各自按照指定算法加密之后,用"."字符连接起来作为jwt发送给客户端。在客户端中,jwt会已httponly的状态保存在cookie中(httponly:无法通过js访问和修改),每次向指定站点发送请求的时候(一般也是这个jwt的发布者),这个jwt都会写在请求头中发送给服务器做数据验证。
dataTable##
一个基于jquery的表格拓展工具,支持多种动态表格功能的使用和开发,高度自定义选项。不过需要引用自己指定的jquery(用前端框架的话),因而会对其他前端工具有覆盖,建议独立出去,然后再以模块的形式引入。
使用过程很简单,首先需要在页面定义一个table,并提供一种方式访问:
<table id="dataTable" class="display">
<thead>
<tr>
<td>id</td>
<td>名字</td>
<td>单位</td>
</tr>
</thead>
</table>
之后调用dataTable为jquery添加的接口dataTable/DataTable即可,当然,如果使用的是前端框架,则需要保证在生成页面之后调用接口。
$("#dataTable").DataTable();
dataTable提供了两个版本的接口(dataTable和DataTable),两者的不同之处在于其返回值,dataTable返回的是$("#dataTable"),而DataTable返回的是表的API,可以用来做一些特殊的修改,之后我们会用到。
这样操作完之后,应该就能在页面上显示一个0参数的dataTable表格了。
表格的作用是用来呈现数据,dataTable允许我们直接把数据填写进表格中,或者定义成js数组,但这在实际生产过程中是不太现实的。绝大多数的数据都会以ajax请求返回值的形式发送给dataTable,因此,我们需要在调用接口的时候给出指定的参数
$("#dataTable").DataTable({
ajax: "/json/data.txt"
});
这样,我们就可以获取到本地服务器静态目录json下的data.txt文件了。这里除了填写url之外,我们还可以填写完整的ajax参数表,即
$("#dataTable").DataTable({
ajax: {
url: "/json/data.txt",
data: {
from: 0,
to: -1,
}
}
});
dataTable的ajax和jquery的基本一样,但是有个参数需要特别注意,即dataSrc,这个参数的意义在于指定这个返回值的key,比如一般的json返回为:{data: [...]},那么这时候就需要指定dataSrc为"data"了。当然如果不指定,dataSrc的默认值就是"data";如果没有键值,则指定空字符串;如果返回的是XML格式,也可以将dataSrc定义为函数function(json) { ... }以便进行转化。
在ajax中也可以定义success用于接受传过来的结果,不过这貌似会替换dataTable自身的处理函数,所以可以用success检测返回值正不正确,但检测完毕之后应当将处理权交由dataTable。
数据收到后第二步就是应该做项绑定了,传统的ejs方式是做一个循环,根据数据的多少生成多少tr。dataTable提供了列绑定的功能,可以处理简单的数据填充
// 假设返回的数据是
// { data: [ { id: 123, name: "张三", company: [ { name: "煎饼果子学院" } ] } ] }
$("#dataTable").DataTable({
ajax: "/json/data.txt",
columns: [
{data: "id"},
{data: "name"},
{data: "company.0.name"}
]
});
这里,数据是按照列数组的顺序依次绑定的,我们这边还演示了嵌套对象和嵌套数组的处理方法。
数据如果都是这样依次填入的,那我们的工作会很轻松。但实际需求往往会复杂的多:比如想在每行表格的最后一个表格显示一组操作按钮、比如在第一列设定自增长的行ID、比如某列数据是结果中几个参数共同计算的结果。面对那样的情况,简单的列指定是不够的,因此dataTable提供了createdRow回调函数来让我们在数据填充完之后,对每行数据进行进一步的修改
$("#dataTable").DataTable({
ajax: "/json/data.txt",
columns: [
{data: "id"},
{data: "name"},
{data: "company.0.name"}
],
createdRow: (row, data, index) => {
const td0 = $("td", row).eq(0);
td0.html(index);
const td4 = $("td", row).eq(4);
td4.html("");
td4.append("<button>操作</button>");
const td3 = $("td", row).eq(3);
const staffNum = data.company[0].managers.length + data.company[0].workers.length;
td3.html(String(staffNum));
}
});
随着jquery的介入,表格的排版可以变得异常灵活。
行的修改我们用createdRow,表其他部分的修改怎么办呢?比如修改表头。这里我们使用initComplete属性(在初始化完成之后),下面这个例子就是为表头添加下拉列表:
initComplete: (settings, json) => {
// 还记得之前说过的dataTable()和DataTable()的区别吗?这里的话如果之前
// 初始化时用的是DataTable,则其返回值就是api
const api = $("#dataTable").dataTable().api();
api.columns().indexes().flatten().each((i) => {
// 用于指定列的表头生成下拉列表,如果不加这个判断,则所有的th都会包含过滤用的下拉列表
if (i !== 2) { return; }
const column = api.column(i);
// 这里就是jquery表现的时候了,我们往这个列的列头中append一个select
const select = $("<select><option value=''></option></select>")
.appendTo($(column.header()))
.on("change", (event) => {
// 如果下拉表发生了变化,则把选中的项的value作为查询的key组装成正则表达式
// 交给列查询之后重绘
const vlu = $.fn.dataTable.util.escapeRegex($(event.target).val());
column.search(vlu ? "^" + vlu + "$" : "", true, false).draw();
});
// 对该列的数据做group筛选掉重复的,然后排序之后插入select
column.data().unique().sort().each((d, j) => {
select.append("<option value='" + d + "'>" + d + "</option>");
});
});
}
这个例子相对复杂,但通过它,可以有很多拓展的方向。initComplete函数意味着在表绘制完成之后可以进行很多操作(虽然之后用jquery选择器也可以,但从整体的角度来看,在这里面写比较合理);下拉列表可以对列进行操作,那么意味着我们也可以设置其他空间来对列里的项进行整体操作。
至此,对表,我们可以做到随意修改了。但同时会发现,除了表,dataTable会帮我们生成一些其他组件:每页显示的项数、查找框、信息、分页。这些东西也可以通过设置初始化参数来操作,我们可以分配给dataTable一个dom属性,该属性是一个字符串,dataTable的设计者开发了一组简易的组件标识,然后配合类似于xml的结构组装起来,便可以对表以及表四周的这一套组件进行定位了
// <> - 代表一个div,可以指定类和id,id的指定和jquery一样:#id,不同的是类,
// 类单独存在的时候,类不需要在类名前加【.】
// l - Length changing 每页显示多少条数据选项
// f - Filtering input 搜索框
// t - The Table 表格
// i - Information 表格信息
// p - Pagination 分页按钮
// r - pRocessing 加载等待显示信息
// 最近写的dataTable模板用的dom(左上角指定id的div是用来存放新建按钮的)
dom: "<'row'<'#btnCreateBtn.col-md-1'><lf>><'row'rt><'row'p>"
可以选择dataTable是否生成某些组件,也可以绑定监听组件的触发事件
// 是否生成组件的选项(设置true/false)
// paging:分页
// ordering:表头排序
// info:表信息
// searching:查找
// lengthChange:页长
// 组件事件(用on来监听,表相关的需要追加dt命名空间)
// page:翻页事件
// length:选择单页显示的项数
// search:查找框变化事件
// processing:请求过程中间事件
table.on("search.dt", (e, settings) => {
console.log(table.search());
});
网友评论