留言板与自定义表单
留言表单怎么写,CSRF 令牌、蜜罐字段、验证码、提交间隔限制这一整套防刷是怎么配合的。
适用范围:单页(联系我们)、详情页、任意需要访客提交的地方。
留言表单
<form method="post" action="{naicha:url type="message"}" data-guard="1">
<input type="hidden" name="_token" value="{naicha:token}">
<input type="hidden" name="form" value="contact">
<!-- 蜜罐:正常人不会填这一栏,填了就判定为机器人 -->
<div style="position:absolute;left:-9999px">
<input type="text" name="website" tabindex="-1" autocomplete="off">
</div>
<input type="text" name="name" required>
<textarea name="content" required></textarea>
<button type="submit">提交</button>
</form>
四个要点:
_token是 CSRF 令牌,缺了会被直接拒绝;website是蜜罐字段,用 CSS 藏起来而不是type="hidden"—— 隐藏域会被机器人识破;data-guard="1"让前端脚本做提交频率限制;form的值要和后台定义的表单名对上(默认contact)。
自定义表单 {naicha:form}
<!-- 后台「表单」里定义过 contact,这里直接输出整张表单 -->
{naicha:form name="contact"}
<!-- 没定义过时退回内置表单,循环体里可用两个变量自己排 -->
{naicha:form name="contact"}
<form method="post" action="{form.action}">
<input type="hidden" name="_token" value="{naicha:token}">
<input type="text" name="{form.name}">
</form>
{/naicha:form}
| 形态 | 行为 |
|---|---|
| 后台定义过这个表单 | 直接输出后台配好的整张表单,循环体被忽略 |
| 后台没定义 | 退回内置表单,循环体里可用 {form.name} {form.action} |
验证码 {naicha:captcha}
<form method="post">
<input type="hidden" name="_token" value="{naicha:token}">
<input type="text" name="name" placeholder="称呼">
{naicha:captcha}
<button type="submit">提交</button>
</form>
站点没开验证码时输出空串,所以模板不用判断开关 —— 开了就有、没开就没有。后台不做这类判断:模板里有没有这个标签是一回事, 服务端要不要校验是另一回事(服务端只认设置开关)。
防刷机制一览
| 机制 | 作用 |
|---|---|
| CSRF 令牌 | 阻止第三方站点伪造你的身份提交 |
| 蜜罐字段 | 拦掉大部分表单机器人 |
| 提交间隔限制 | 同一来源的两次提交之间强制间隔 |
| 登录失败限流 | 15 分钟内失败 5 次即临时锁定该账号 + IP |
| 图形验证码 | 可在设置里开启,进一步抬高自动化成本 |
{naicha:messages} —— 前台留言列表
留言以前只在后台看得见。要把已收到的留言列出来(做"留言板"那类页面),用这个:
{naicha:messages num="20" form="contact"}
<div class="msg">
<b>{msg.name}</b>
<span>{msg.when}</span>
<p>{msg.content}</p>
</div>
{/naicha:messages}
form只看哪张表单收到的(默认全部)num列几条,默认 20{msg.id} {msg.form} {msg.created_at} {msg.date} {msg.when}编号 / 表单名 / 时间{msg.你表单里的字段名}表单里填了什么就能取什么,比如 {msg.name} {msg.contact} {msg.content}
⚠️ 这些是访客提交的原始内容,默认输出会被转义(安全)。
别对它用
⚠️ 留言可能带**姓名、电话、邮箱**。列出来之前想清楚: 这个页面是给所有人看的,还是只给你自己看的。
html="1" —— 那等于让访客往你页面上写 HTML。
⚠️ 留言可能带**姓名、电话、邮箱**。列出来之前想清楚: 这个页面是给所有人看的,还是只给你自己看的。
{naicha:mycomments} —— 我的评论
当前登录会员自己发过的评论(含待审的 —— 那是他自己的东西,看得见才安心)。 放在会员中心或任意登录可见的位置:
{naicha:mycomments num="20"}
<div>
<span>{mycomment.when}</span>
<a href="/detail/{mycomment.content_id}">{mycomment.content}</a>
</div>
{/naicha:mycomments}
字段与 {naicha:commentlist} 完全一致,前缀换成 {mycomment.…}。
未登录时输出空串,所以模板不用自己判断登录。
