“非法访问”是代码手动抛出或第三方拦截导致的,非layui原生错误;主因是接口返回非标准json(如html登录页),而parsedata未做兜底校验,导致res.data访问失败。
为什么 table.render() 会报“非法访问”?
这个提示不是浏览器报的,也不是 Layui 官方错误码,而是你代码里手动 throw 的、或第三方拦截脚本(比如某些后台权限 SDK)触发的。Layui 本身不会抛出这句话。最常见的情况是:你在 table.render() 的 url 配置里写了后端接口地址,但该接口返回了非 200 状态码(如 401/403),而你又在 parseData 或 done 回调里没做响应体校验,直接取 res.data —— 结果 res 是个空对象或 HTML 登录页内容,data 属性就访问不到,JS 报 Cannot read property 'data' of undefined,被上层 try/catch 捕获后误标为“非法访问”。
- 后端返回 401 时,响应体可能是重定向 HTML 或纯文本,不是标准 JSON
-
parseData 函数里硬写 return { data: res.data },但 res.data 根本不存在
- 使用了代理或 nginx,把接口请求悄悄重定向到了登录页(返回 200 + HTML),Layui 以为成功了,结果解析失败
parseData 必须做响应结构兜底
别信后端说“一定返回标准格式”。只要没在前端做防御性解析,就一定会栽。
- 用
typeof res === 'object' 初步判断是否为 JSON 响应
- 检查
res 是否有 code 字段(或你约定的成功字段),再决定是否取 data
- 如果解析失败,显式 return 一个空数组 + 提示,避免静默崩溃
parseData: function(res){
// 后端可能返回字符串、HTML、空对象、甚至 null
if (!res || typeof res !== 'object') {
layer.msg('数据加载异常,请刷新重试');
return { data: [] };
}
// 假设后端约定 code === 0 表示成功
if (res.code !== 0) {
layer.msg(res.msg || '请求失败:' + res.code);
return { data: [] };
}
return {
data: res.data || [],
count: res.count || 0
};
}
接口返回 HTML 而不是 JSON 怎么发现?
这是最隐蔽的坑。明明配了 url: '/api/list',却总卡在“非法访问”,大概率是请求被服务端跳转了。
打开浏览器开发者工具 → Network → 找到那个 /api/list 请求 → 点开 → 看 Preview 或 Response 标签页
如果里面显示的是 开头,或者有 <title>请先登录</title>,说明已被重定向到登录页
查看 Response Headers 中的 Location 字段,或 Status 是否是 302/301
检查 nginx 配置、Spring Security / Shiro 权限拦截规则、或后端中间件是否对未登录用户自动跳转
不要依赖状态码判断:有些代理会把 401 改成 200 再塞 HTML
在 beforeSend 或全局 ajaxSetup 里加 header(如 X-Requested-With: XMLHttpRequest),让后端识别是 AJAX 请求,不跳转
动态传参导致 URL 拼错或编码问题table.reload() 时用字符串拼接参数,容易漏 encode 或多加斜杠。
where: { keyword: $('#kw').val() } 比 url: '/api/list?keyword=' + $('#kw').val() 更安全
如果必须拼 URL,用 encodeURIComponent() 包裹值,尤其含中文、空格、& 符号时
检查最终发出的请求地址是否多了一个 //(比如 base url 以 / 结尾,又在 path 前加了 /)
Layui 对 URL 中的 ? 和 & 没有自动编码逻辑,全靠你写对
table.render() 初始化后,不要手动改 table.config[xxx].url,要用 table.reload()
parseData 函数里硬写 return { data: res.data },但 res.data 根本不存在 parseData 必须做响应结构兜底
别信后端说“一定返回标准格式”。只要没在前端做防御性解析,就一定会栽。
- 用
typeof res === 'object'初步判断是否为 JSON 响应 - 检查
res是否有code字段(或你约定的成功字段),再决定是否取data - 如果解析失败,显式 return 一个空数组 + 提示,避免静默崩溃
parseData: function(res){
// 后端可能返回字符串、HTML、空对象、甚至 null
if (!res || typeof res !== 'object') {
layer.msg('数据加载异常,请刷新重试');
return { data: [] };
}
// 假设后端约定 code === 0 表示成功
if (res.code !== 0) {
layer.msg(res.msg || '请求失败:' + res.code);
return { data: [] };
}
return {
data: res.data || [],
count: res.count || 0
};
}
接口返回 HTML 而不是 JSON 怎么发现?
这是最隐蔽的坑。明明配了 url: '/api/list',却总卡在“非法访问”,大概率是请求被服务端跳转了。
打开浏览器开发者工具 → Network → 找到那个 /api/list 请求 → 点开 → 看 Preview 或 Response 标签页
如果里面显示的是 开头,或者有 <title>请先登录</title>,说明已被重定向到登录页
查看 Response Headers 中的 Location 字段,或 Status 是否是 302/301
检查 nginx 配置、Spring Security / Shiro 权限拦截规则、或后端中间件是否对未登录用户自动跳转
不要依赖状态码判断:有些代理会把 401 改成 200 再塞 HTML
在 beforeSend 或全局 ajaxSetup 里加 header(如 X-Requested-With: XMLHttpRequest),让后端识别是 AJAX 请求,不跳转
动态传参导致 URL 拼错或编码问题table.reload() 时用字符串拼接参数,容易漏 encode 或多加斜杠。
where: { keyword: $('#kw').val() } 比 url: '/api/list?keyword=' + $('#kw').val() 更安全
如果必须拼 URL,用 encodeURIComponent() 包裹值,尤其含中文、空格、& 符号时
检查最终发出的请求地址是否多了一个 //(比如 base url 以 / 结尾,又在 path 前加了 /)
Layui 对 URL 中的 ? 和 & 没有自动编码逻辑,全靠你写对
table.render() 初始化后,不要手动改 table.config[xxx].url,要用 table.reload()
打开浏览器开发者工具 → Network → 找到那个 /api/list 请求 → 点开 → 看 Preview 或 Response 标签页
如果里面显示的是 开头,或者有 <title>请先登录</title>,说明已被重定向到登录页
查看 Response Headers 中的 Location 字段,或 Status 是否是 302/301
检查 nginx 配置、Spring Security / Shiro 权限拦截规则、或后端中间件是否对未登录用户自动跳转
不要依赖状态码判断:有些代理会把 401 改成 200 再塞 HTML
在 beforeSend 或全局 ajaxSetup 里加 header(如 X-Requested-With: XMLHttpRequest),让后端识别是 AJAX 请求,不跳转
table.reload() 时用字符串拼接参数,容易漏 encode 或多加斜杠。
where: { keyword: $('#kw').val() }比url: '/api/list?keyword=' + $('#kw').val()更安全如果必须拼 URL,用
encodeURIComponent()包裹值,尤其含中文、空格、& 符号时检查最终发出的请求地址是否多了一个
//(比如 base url 以/结尾,又在 path 前加了/)Layui 对 URL 中的
?和&没有自动编码逻辑,全靠你写对table.render()初始化后,不要手动改table.config[xxx].url,要用table.reload()
Layui 表格的“非法访问”基本都卡在响应体解析这一环,而不是权限控制本身。真正该盯住的,是 Network 面板里那个请求的真实返回内容——它不说谎。











