html input

html input <input type="value0"> hidden 定义隐藏的输入字段。 Hidden 对象代表一个 HTML 表单中的某个隐藏输入域。 这种类型的输入元素实际上是隐藏的。这个不可见的表单元素的 value 属性保存了一个要提交给 Web 服务器的任意字符串。如果想要提交并非用户直接输入的数据的话,就是用这种类型的元素。 在 HTML 表单中 <input type="hidden"> 标签每出现一次,一个 Hidden 对象就会被创建。 您可通过遍历表单的 elements[] 数组来访问某个隐藏输入域,或者通过使用document.getElementById()。 http://www.w3school.com.cn/jsref/dom_obj_hidden.asp http://www.wiloon.com/?p=6529 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;categories 改为 Web 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 10106-06-10 · Updated 9096-10-09 · 1 min · 46 words · -

tomcat autoDeploy="false" deployOnStartup="false"

’tomcat autoDeploy=“false” deployOnStartup=“false”' https://stackoverflow.com/questions/26884335/tomcat-deploy-only-manager-on-startup From the Apache 6 documentation: https://tomcat.apache.org/tomcat-6.0-doc/config/context.html in the Attributes section of Context, the documentation for the path attribute specifies: This attribute must only be used when statically defining a Context in server.xml. In all other circumstances, the path will be inferred from the filenames used for either the .xml context file or the docBase. Even when statically defining a Context in server.xml, this attribute must not be set unless either the docBase is not located under the Host’s appBase or both deployOnStartup and autoDeploy are false. If this rule is not followed, double deployment is likely to result. ...

Created 19196-09-19 · Updated 9096-10-09 · 1 min · 157 words · -

XSS, Cross Site Scripting, CSRF, Cross-site request forgery, CORS

CORS, XSS, Cross Site Scripting, CSRF, Cross-site request forgery CORS, Cross-Origin Resource Sharing, 跨源资源共享, 跨域资源共享 CORS (Cross-Origin Resource Sharing,跨源资源共享) 是一种基于 HTTP 头的机制,允许服务器指示浏览器应该允许哪些源(域、协议或端口)来访问其资源。 核心概念 同源策略 (Same-Origin Policy) 同源策略是浏览器最核心的安全机制之一,用于隔离潜在的恶意文档,防止不同源的网页之间互相干扰。 默认情况下, 网页只能请求与自身同源的资源。 什么是"同源": 两个 URL 只有在以下三个部分完全相同时才被认为是同源的: 协议 (Protocol): http/https 域名 (Domain): 包括子域名 端口 (Port): 默认端口可省略 假设当前页面是: http://www.example.com:80/dir/page.html http://www.example.com/dir2/other.html ✅ 同源 协议、域名、端口相同 http://www.example.com:80/dir/inner/page.html ✅ 同源 80 是 http 默认端口 https://www.example.com/page.html ❌ 不同源 协议不同 (https vs http) http://www.example.com:8080/page.html ❌ 不同源 端口不同 (8080 vs 80) http://api.example.com/page.html ❌ 不同源 域名不同 (子域名不同) http://example.com/page.html ❌ 不同源 域名不同 (缺少 www) ...

Created 13136-12-13 · Updated 9096-10-09 · 4 min · 655 words · -

antisamy

antisamy https://blog.csdn.net/zhujq_icode/article/details/79154063 策略文件 antisamy-slashdot.xml Slashdot (http://www.slashdot.org/)是一个提供技术新闻的网站,它允许用户用有限的HTML是一个提供技术新闻的网站,它允许用户用有限的HTML)格式的内容匿名回帖。 Slashdot不仅仅是目前同类中最酷的网站之一,而且同时也曾是最容易被成功攻击的网站之一。更不幸的是,导致大部分用户遭受攻击的原由是臭名昭着的goatse.cx 图片(请你不要刻意去看)。 Slashdot的安全策略非常严格: 用户只能提交下列的html标签: <b>、<u>、<i>、<a>、<blockquote>,并且还不支持CSS.因此我们创建了这样的策略文件来实现类似的功能。它允许所有文本格式的标签来直接修饰字体、颜色或者强调作用。 antisamy-ebay.xml 众所周知,eBay (http://www.ebay.com/)是当下最流行的在线拍卖网站之一。它是一个面向公众的站点,因此它允许任何人发布一系列富HTML的内容。我们对eBay成为一些复杂XSS攻击的目标,并对攻击者充满吸引力丝毫不感到奇怪。由于eBay允许输入的内容列表包含了比Slashdot是当下最流行的在线拍卖网站之一。它是一个面向公众的站点,因此它允许任何人发布一系列富HTML的内容。我们对eBay成为一些复杂XSS攻击的目标,并对攻击者充满吸引力丝毫不感到奇怪。由于eBay允许输入的内容列表包含了比Slashdot)更多的富文本内容,所以它的受攻击面也要大得多。 antisamy-myspace.xml MySpace (http://www.myspace.com/)是最流行的一个社交网站之一。用户允许提交几乎所有的他们想用的HTML和CSS,只要不包含JavaScript。MySpace现在用一个黑名单来验证用户输入的HTML,这就是为什么它曾受到Samy蠕虫攻击(http://namb.la/)的原因。Samy蠕虫攻击利用了一个本应该列入黑名单的单词(eval)来进行组合碎片攻击的,其实这也是AntiSamy是最流行的一个社交网站之一。用户允许提交几乎所有的他们想用的HTML和CSS,只要不包含JavaScript。MySpace现在用一个黑名单来验证用户输入的HTML,这就是为什么它曾受到Samy蠕虫攻击(http://namb.la/)的原因。Samy蠕虫攻击利用了一个本应该列入黑名单的单词(eval)来进行组合碎片攻击的,其实这也是AntiSamy)立项的原因。 antisamy-anythinggoes.xml 如果你想允许所有有效的HTML和CSS元素输入 (但能拒绝JavaScript或跟CSS相关的网络钓鱼攻击) ,你可以使用这个策略文件。其实即使MySpace也没有这么疯狂。然而,它确实提供了一个很好的参考,因为它包含了对于每个元素的基本规则,所以你在裁剪其它策略文件的时候可以把它作为一个知识库。 antisamy-tinymce.xml 只允许文本格式通过,相对较安全 antisamy.xml 默认规则,允许大部分HTML通过 作者: flying_pig1989 来源: CSDN 原文: https://blog.csdn.net/zhujq_icode/article/details/79154063 版权声明: 本文为博主原创文章,转载请附上博文链接! 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;categories 改为 Web 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 14146-12-14 · Updated 9096-10-09 · 1 min · 51 words · -

angular material

angular material yarn add @angular/material @angular/cdk @angular/animations app.module.ts import { MatSliderModule } from '@angular/material/slider'; import 'hammerjs'; … @NgModule ({.... imports: [..., MatSliderModule, …] }) app.component.html <mat-slider min="1" max="100" step="1" value="1"></mat-slider> styles.css @import '@angular/material/prebuilt-themes/deeppurple-amber.css'; https://material.angular.io/ https://material.angular.cn/guides https://github.com/stbui/angular-material-app/tree/master/src/app https://material.io/ https://material.angular.io/components/categories 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;categories 改为 Web 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 8086-06-08 · Updated 9096-10-09 · 1 min · 56 words · -

CSS 选择器优先级与匹配原理

CSS选择器 优先级 匹配原理 http://developer.51cto.com/art/201009/226852.htm 作为一个Web开发者,掌握必要的前台技术也是很重要的,特别是在遇到一些实际问题的时候。这里给大家列举一个例子: 给一个p标签增加一个类 (class) ,可是执行后该class中的有些属性并没有起作用。通过Firebug查看,发现没有起作用的属性被覆盖了。这个时候突然意识到了CSS选择器的优先级问题,这里就CSS选择器的优先级问题做了一些总结。 51CTO推荐阅读: 巧妙地使用CSS选择器 选择器种类 严格来讲,选择器的种类可以分为三种: 标签名选择器、类选择器和ID选择器。而所谓的后代选择器和群组选择器只不过是对前三种选择器的扩展应用。而在标签内写入style=““的方式,应该是CSS的一种引入方式,而不是选择器,因为根本就没有用到选择器。而一般人们将上面这几种方式结合在一起,所以就有了5种或6种选择器了。 三种基本的选择器类型 语法如下: ◆标签名选择器,如: p{},即直接使用HTML标签作为选择器。 ◆类选择器,如.polaris{}。 ◆ID选择器,如#polaris{}。 注意,ID选择器跟类选择器有很大的不同: 一个页面内不能出现相同的ID;再就是ID也是后台开发人员会经常用的,所以前端开发人员应该尽量少的使用。当然跟后台人员的工作配合十分娴熟之后,这些都不会成为限制。 扩展选择器 ◆后代选择器,如.polaris span img{},后代选贼器实际上是使用多个选择器加上中间的空格来找到具体的要控制标签。 ◆群组选择器,如div,span,img{},群组选择器实际上是对CSS的一种简化写法,只不过把有相同定义的不同选择器放在一起,省了很多代码。 选择器的优先级别 了解了各种选择器后,还有一个重要的知识点就是CSS选择器的优先级。这也就是为什么polaris会遇到文章开头的问题。举个简单的例子: beijixing polaris 如果已经把.polaris下面span内的字体设置成红色: .polaris span {color:red;} 这时,如果要改变.beijixing的颜色为蓝色,用下面的命令是不能实现的: .beijixing {color:blue;} 出现这种情况就是因为后一个命令的优先级不够,两条相互冲突的样式设置,浏览器只会执行优先级较高的那个。 那么选择器的优先级是怎么规定的呢? 一般而言,选择器越特殊,它的优先级越高。也就是选择器指向的越准确,它的优先级就越高。通常我们用1表示标签名选择器的优先级,用10表示类选择器的优先级,用100标示ID选择器的优先级。比如上例当中 .polaris span {color:red;}的选择器优先级是 10 + 1 也就是11;而 .polaris 的优先级是10;浏览器自然会显示红色的字。理解了这个道理之后下面的优先级计算自是易如反掌: div.test1 .span var 优先级 1+10 +10 +1 span#xxx .songs li 优先级1+100 + 10 + 1 #xxx li 优先级 100 +1 对于什么情况下使用什么选择器,用不同选择器的原则是: 第一: 准确的选到要控制的标签;第二: 使用最合理优先级的选择器;第三: HTML和CSS代码尽量简洁美观。通常: ...

Created 1016-01-01 · Updated 9096-10-09 · 1 min · 166 words · -

HTML Basic

html basic button <button name="button0">button0</button> HTML Formatting Elements <b> - Bold text <strong> - Important text <i> - Italic text <em> - Emphasized text <mark> - Marked text <small> - Smaller text <del> - Deleted text <ins> - Inserted text <sub> - Subscript text <sup> - Superscript text <br> - line break node type ELEMENT_NODE (元素节点):值为 1 ATTRIBUTE_NODE (属性节点):值为 2 TEXT_NODE (文本节点):值为 3 CDATA_SECTION_NODE (CDATA区段节点):值为 4 ENTITY_REFERENCE_NODE (实体引用节点):值为 5 (在HTML中不常见) ENTITY_NODE (实体节点):值为 6 (在HTML中不常见) PROCESSING_INSTRUCTION_NODE (处理指令节点):值为 7 COMMENT_NODE (注释节点):值为 8 DOCUMENT_NODE (文档节点):值为 9 DOCUMENT_TYPE_NODE (文档类型节点):值为 10 DOCUMENT_FRAGMENT_NODE (文档片段节点):值为 11 NOTATION_NODE (符号节点):值为 12 (在HTML中不常见) 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;title 改为「HTML Basic」;url 改为 html-basic;categories 改为 Web 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 29296-09-29 · Updated 9096-10-09 · 1 min · 115 words · -

Vue

vue basic Vue 3 npm init vue@latest 构建工具链 Vue 3 官方脚手架从 Vue CLI(基于 Webpack)切换到了 Vite。 工具分层 层次 Vue CLI 时代 Vite 时代 工具链 Vue CLI + Webpack Vite 转译器 Babel esbuild 打包器 Webpack Rollup(生产) 压缩 Terser esbuild(默认) Babel vs esbuild 两者都是 JS 转译器(Transpiler),核心职责相同:把现代 JS/TS/JSX 语法转换成目标环境能运行的 JS。 Babel esbuild 实现语言 JavaScript Go 速度 慢 快 10-100x 可扩展性 插件生态极其丰富 插件有限 功能边界 只转译 转译 + 打包都能做 适合场景 需要复杂插件、polyfill 追求速度的现代项目 Rollup Rollup 是一个 JS 模块打包器(Bundler),解决的核心问题是:把多个 JS 模块文件合并成一个(或少数几个)输出文件。 ...

Created 30306-04-30 · Updated 9096-10-09 · 5 min · 872 words · -

Chrome Extension 开发笔记

chrome extension content script, 只能访问 dom, 不能访问页面 js 变量和函数 Injected Script, 被插入到页面里的 js 代码 chrome://extensions puzzle button: chrome extension 图标后面的拼图按钮 develop chrome extension doc https://developer.chrome.com/docs/extensions/mv3/ javascript web api: https://developer.mozilla.org/en-US/docs/Web/API chrome api: https://developer.mozilla.org/en-US/docs/Web/API html: https://web.dev/learn/html/ css: https://web.dev/learn/css/ javascript: https://developer.mozilla.org/en-US/docs/Learn/JavaScript chrome extension development overview: https://developer.chrome.com/docs/extensions/mv3/devguide/ chrome extension 的构成 The manifest, manifest.json, 唯一一个必须要存在于 extension 根目录的文件 The service worker, service worker 监听 chrome 的各种事件, 可以调用 Chrome api, 但是不能直接操作页面内容 Content scripts: content script 可以直接在页面中执行 js 代码, 可以直接操作 DOM, 还可以跟 service worker 通信 The popup and other pages content script 与 service worker 的分工和通信 各自负责什么 对比项 content script service worker(background) 运行位置 注入到网页里,每个匹配的 tab(以及 all_frames 打开时的每个 frame)各一份 整个扩展只有一个,运行在扩展自己的后台 DOM 能读写所在页面的 DOM 没有 DOM,也没有 window、document、localStorage 页面的 JS 变量 访问不到,运行在 isolated world 访问不到 可用的 chrome API 只有一小部分:chrome.runtime(发消息、getURL 等)、chrome.storage、chrome.i18n 按 manifest 里申请的 permissions 全部可用:tabs、scripting、cookies、alarms、contextMenus 等 网络请求 fetch() 按所在页面的 origin 处理,受页面 CORS 限制 对 host_permissions 里的域名 fetch() 不受 CORS 限制 生命周期 跟着页面走,页面刷新或关闭就没了 事件驱动,空闲约 30 秒被回收,有事件再拉起(见下一节) 一句话概括:content script 负责“页面里看得见的部分”,比如读取用户选中的文字、在页面上插入按钮或浮层;service worker 负责“页面之外的部分”,比如调用后端 API、保存登录 token、管理 tab、响应扩展图标点击和右键菜单。两边都做不了对方的事,所以绝大多数扩展功能都是两者配合完成的。 ...

Created 21216-04-21 · Updated 4046-10-04 · 4 min · 801 words · -

HTTP Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, QUERY

HTTP Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, QUERY https://www.cnblogs.com/machao/p/5788425.html HTTP Method 的历史: HTTP 0.9 这个版本只有 GET 方法 HTTP 1.0 这个版本有 GET HEAD POST 这三个方法 HTTP 1.1 这个版本是当前版本,包含 GET HEAD POST OPTIONS PUT DELETE TRACE CONNECT 这 8 个方法 之后单独用 RFC 追加的方法:PATCH(RFC 5789,2010 年,部分修改资源)、QUERY(RFC 10008,2026 年 6 月,带请求体的安全查询,见下文 QUERY) 我们先看看HTTP 1.1 规范的中文翻译 方法定义 (Method Definitions) HTTP/1.1常用方法的定义如下。虽然方法可以被展开,但新加的方法不能认为能分享与扩展的客户端和服务器同样的语义。 Hst 请求头域 (见13.23节) 必须能在所有的HTTP/1.1请求里出现。 9.1 安全和等幂 (Idempotent) 方法 9.1.1 安全方法 (Safe Methods) 实现者应当知道软件是代表用户在互联网上进行交互,并且应该小心地允许用户知道任何它们可能采取的动作(action),这些动作可能给他们自己或他人带来无法预料的结果。 ...

Created 29296-09-29 · Updated 29296-09-29 · 6 min · 1210 words · -

WeChat QR to PDF: 微信扫码查看与下载 PDF

设计目标:用户用微信扫事先印好的二维码,在手机里查看 PDF,并能下载。技术栈固定为自购域名、GitHub 私有仓库、Cloudflare Pages、离线生成二维码。不使用 Hugo,也不需要后端。 域名购买、DNS 切到 Cloudflare、Pages 绑自定义域名的操作步骤,与本站博客相同,见 Hugo + Cloudflare Pages 搭建个人博客。本文只写和「微信扫码 + PDF」有关的设计选择。 目标与非目标 目标 微信扫码打开 HTTPS 页面,能预览 PDF 页面上提供下载 PDF 源文件放在 GitHub 私有仓库里,不在 GitHub 网页上公开浏览 更新 PDF 时尽量不换二维码(同一 URL 覆盖文件即可) 非目标 不做登录、不做按人授权。知道链接的人都能打开 不接入微信公众号、JS-SDK、微信支付 不在微信里做「仅好友可见」之类的权限 单文件超过 Cloudflare Pages 限制(25 MiB)时,本方案不够,需改对象存储 整体结构 二维码里只放一个 URL,不放 PDF 本身。扫码等于用微信内置浏览器打开这个地址。 Printed QR --> https://files.example.com/catalog/ | +-- index.html landing page +-- catalog.pdf the file 组件 作用 自购域名 二维码里的长期地址,例如 files.example.com GitHub 私有仓库 存放 HTML 和 PDF,只有仓库成员能在 GitHub 上看到 Cloudflare Pages 从私有仓库拉取并托管静态文件,对外提供 HTTPS 二维码图片 事先生成、打印或贴到物料上,内容是落地页 URL 仓库私有只挡住 GitHub 上的浏览和 clone。部署到 Pages 之后,站点是公开的。这是预期行为:扫码的人没有 GitHub 账号,也必须能打开。 ...

Created 28286-08-28 · Updated 28286-08-28 · 2 min · 413 words · -

Web API Notes: Popover API 与标准化

这篇文档的定位 这是一篇持续更新的 Web API 笔记。Popover API 是第一个案例,后续可以继续补充其他 API(例如 View Transitions API、Clipboard API、Web Share API)。 Web API 是什么 可以把 Web API 理解为浏览器提供给页面脚本调用的一组能力。页面里的 JavaScript 通过这些接口访问浏览器功能,例如: 读写 DOM(DOM API) 网络请求(Fetch API) 本地存储(Storage API) 弹出层控制(Popover API) 所以你的理解是对的:页面里的 JavaScript 脚本可以调用这些 API 来实现功能。 Web API、Chrome API、标准的关系 不是所有“在 Chrome 里能用的 API”都等于通用 Web 标准,通常分三类: 标准 Web API:由标准组织和浏览器厂商协作制定,多个浏览器逐步实现(Popover API 属于这一类)。 实验性能力:可能还在提案/试验阶段,通常带实验标记或只在预览版本可用。 浏览器专有 API:某个浏览器或生态特有,不保证跨浏览器可用(常见于扩展平台能力)。 Web 标准通常由谁推进 WHATWG:维护 HTML、DOM 等活标准,很多 Web API 在这里落地。 W3C:维护和推进大量 Web 标准生态工作。 TC39:负责 JavaScript 语言本身(例如语法和内建对象),不直接定义 Popover 这类 DOM/UI API。 浏览器厂商协作机制:通过提案、实现、互通测试(例如 Web Platform Tests)持续收敛行为一致性。 简单说:Popover API 不是“Chrome 私有接口”,而是 Web 标准体系中的 API;Chrome 只是较早实现的浏览器之一。 ...

Created 31316-07-31 · Updated 31316-07-31 · 2 min · 296 words · -

Hugo + Cloudflare Pages 搭建个人博客

本文记录这个博客的搭建方式,从买域名到发布一个静态站点。技术选型和步骤与本站的实现保持一致。 这套技术栈长什么样 一句话概览:用 Hugo 把 Markdown 编译成静态页面,源码在 GitHub,Cloudflare Pages 连接 GitHub 仓库并在 Cloudflare 侧构建、托管,域名解析和 CDN 也在 Cloudflare。 各部分的分工: 组件 作用 Hugo 静态站点生成器,把 content/ 下的 Markdown 编译成 HTML GitHub 存放源码,作为部署的触发源 Cloudflare Pages 连接 GitHub 仓库,执行 hugo --minify 构建并托管产物 Cloudflare DNS 域名解析,把自定义域名指向 Pages 项目 Cloudflare CDN 边缘缓存与加速,Pages 默认自带 整个流程没有用 GitHub Actions,也没有容器化构建,构建这一步完全由 Cloudflare Pages 在它自己的环境里完成。基础站点的构建命令就是一句 hugo --minify;本站为了顺带生成搜索索引,把它包成了一个很短的脚本(见下文进阶模块),思路一样。 基础模块 这一部分从 0 到「能访问」。 买域名 域名可以在任意注册商购买,我最早是在 GoDaddy 买的。以 GoDaddy 为例: 打开 godaddy.com,在搜索框里输入想要的域名,看是否可注册。 选一个后缀(.com、.dev 等),加入购物车,结账。注意第一年常有促销价,续费价通常更高,下单前看清续费价格。 结账时可关掉 GoDaddy 自家的一堆增值服务(邮箱、隐私保护等),后面把 DNS 切到 Cloudflare 后这些大多用不上。 Cloudflare 自己也能直接注册域名(Cloudflare Registrar,按批发价、免费 WHOIS 隐私保护),但支持的后缀有限。如果想要的后缀在它的列表里,直接在 Cloudflare 买、省去后面改 Nameserver 的步骤也可以;后缀不在列表里就按上面的思路在别的注册商买,再把 DNS 切过来。 ...

Created 9096-07-09 · Updated 9096-07-09 · 3 min · 452 words · -

CSRF/XSRF

CSRF/XSRF CSRF (Cross-site request forgery) 跨站请求伪造,也被称成为"one click attack"或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本 (XSS) ,但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行 (因此对其进行防范的资源也相当稀少) 和难以防范,所以被认为比XSS更具危险性。攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作。例如: 一个网站用户 Bob 可能正在浏览论坛,而同时另一个用户 Alice 也在此论坛中,并且后者刚刚发布了一个具有 Bob 银行链接的图片消息。设想一下,Alice 编写了一个在 Bob 的银行站点上进行取款的 form 提交的链接,并将此链接作为图片 tag。如果 Bob 的银行在 cookie 中保存他的授权信息,并且此 cookie 没有过期,那么当 Bob 的浏览器尝试装载图片时将提交这个取款 form 和他的 cookie,这样在没经 Bob 同意的情况下便授权了这次事务。 CSRF 是一种依赖 web 浏览器的、被混淆过的代理人攻击 (deputy attack) 。在上面银行示例中的代理人是 Bob 的 web 浏览器,它被混淆后误将 Bob 的授权直接交给了 Alice 使用。 下面是CSRF的常见特性: 依靠用户标识危害网站 利用网站对用户标识的信任 欺骗用户的浏览器发送HTTP请求给目标站点 另外可以通过IMG标签会触发一个GET请求,可以利用它来实现CSRF攻击。风险在于那些通过基于受信任的输入form和对特定行为无需授权的已认证的用户来执行某些行为的web应用。已经通过被保存在用户浏览器中的cookie进行认证的用户将在完全无知的情况下发送HTTP请求到那个信任他的站点,进而进行用户不愿做的行为。 使用图片的CSRF攻击常常出现在网络论坛中,因为那里允许用户发布图片而不能使用JavaScript。贴图只是GET的方式,很多时候我们需要伪造POST的请求。一个办法是利用跨站,当然目标站点可能不存在跨站,这个时候我们可以从第三方网站发动攻击。 比如我要攻击一个存在问题的blog,那就先去目标blog留言,留下一个网址,诱其主人点击过来 (这个就要看你的忽悠本事咯:p) ,然后构造个HTML表单提交些数据过去。 多窗口浏览器就帮了一点忙。 多窗口浏览器 (firefox、遨游、MyIE……) 便捷的同时也带来了一些问题,因为多窗口浏览器新开的窗口是具有当前所有会话的。即我用IE登陆了我的Blog,然后我想看新闻了,又运行一个IE进程,这个时候两个IE窗口的会话是彼此独立的,从看新闻的IE发送请求到Blog不会有我登录的cookie;但是多窗口浏览器永远都只有一个进程,各窗口的会话是通用的,即看新闻的窗口发请求到Blog是会带上我在blog登录的cookie。 想一想,当我们用鼠标在Blog/BBS/WebMail点击别人留下的链接的时候,说不定一场精心准备的CSRF攻击正等着我们。 前后端分离架构下还有 CSRF 风险吗 前后端分离本身不是防 CSRF 的银弹,关键要看前端如何保存和发送身份凭证。 ...

Created 15156-07-15 · Updated 2026-07-02 · 1 min · 194 words · -

JWT vs Session:认证方式对比

背景知识 github.com/golang-jwt/jwt Authentication 和 Authorization 的区别 Authentication: 认证,指的是验证用户的身份,例如你希望以 A 的身份登录,那么应用程序需要通过用户名和密码确认你真的是 A 。 Authorization: 授权,指的是确认你的身份之后提供给你权限,例如用户 A 可以修改数据,而用户 B 只能阅读数据。 由于 http 协议是无状态的,每一次请求都无状态。当一个用户通过用户名和密码登录了之后,他的下一个请求不会携带任何状态,应用程序无法知道他的身份,那就必须重新认证。因此我们希望用户登录成功之后的每一次 HTTP 请求,都能够保存他的登录状态。 目前主流的用户认证方法有基于 token 和基于 session 两种方式,常见的还有三种细分形态: 无状态 JWT (Stateless JWT):包含 Session 数据的 JWT Token,Session 数据直接编码进 Token 内。 有状态 JWT (Stateful JWT):包含 Session 引用或其 ID 的 JWT Token,Session 数据存储在服务端。 Session token(又称 Session cookie):标准的、可被签名的 Session ID,例如各类 Web 框架 (译者注: 包括 Laravel) 内已经使用了很久的 Session 机制,Session 数据同样存储在服务端。 以上背景知识整理自 Wi1dcard 的文章,原文地址:https://learnku.com/articles/22616(版权归原作者所有,商业转载请联系作者获得授权)。 Session vs JWT 详解 以下内容整理自 chengkai 的文章《聊一聊JWT与session》,原文地址:https://juejin.cn/post/6844903542449242126(版权归原作者所有)。 ...

Created 23236-05-23 · Updated 2026-07-02 · 4 min · 799 words · -

Refresh Token Rotation: 刷新令牌轮换与重放检测

OAuth2 / JWT 体系里的 refresh token,如果只靠"签名 + 过期时间"校验,是无状态的:服务端不记录任何已发放、已使用的记录,因此没法检测重放、也没法单独撤销某一次登录。要补齐这块安全能力,业界通用做法叫 refresh token rotation(轮换)+ reuse detection(重放检测),思路和 Spring Security 的持久化 remember-me(见 Spring Security Remember Me 实现机制)几乎一致,只是术语不同。 无状态 refresh token 的问题 最简单的实现:refresh token 就是一个长期有效的签名字符串,服务端只验证签名和过期时间,不查库。 优点:无状态,扩展性好。 缺陷:refresh token 一旦泄露,在过期之前可以被无限次使用,服务端发现不了,也撤销不了单独一次登录(除非撤销全部密钥或拉黑名单)。 这跟 Spring Security 默认的 TokenBasedRememberMeServices(哈希令牌)是同一类问题:都是"无状态签名",天然缺少重放检测和单点撤销能力。 Rotation + Reuse Detection 的做法 给每一条 refresh token 的"血统"维护一个 family_id(有的实现里叫 session_id、lineage_id,作用等价于 remember-me 里的 series): family_id current_token issued_at used 用户登录时,颁发 family_id + 第一个 refresh_token,同时记录到数据库。 客户端用 refresh_token 换新的 access_token 时,服务端同时颁发一个新的 refresh_token,旧值作废,数据库里 current_token 更新为新值。 如果收到的 refresh_token 匹配 family_id 但不等于数据库里记录的 current_token——说明这个 token 已经被换过一次了,现在又被用了一次,只有两种可能:客户端重复提交,或者 token 被别人窃取后重放。 一旦判定为重放,直接撤销整条 family_id,强制该登录下线重新认证。 这跟持久化 remember-me 的判定逻辑完全对应: ...

Created 2026-07-02 · Updated 2026-07-02 · 1 min · 164 words · -

Servlet Filter

Servlet Filter Filter 是 Servlet 规范里的一种组件,位于容器和目标资源(Servlet/JSP)之间,可以在请求到达目标资源之前、响应离开目标资源之后做统一处理。Filter 本身不产生响应内容,只负责预处理和后处理,典型用途包括: 身份校验、权限校验 请求/响应日志记录 请求头、响应头改写 内容压缩、编码转换 多个 Filter 可以按声明顺序串成一条链(Filter Chain),这也是 责任链模式(Chain of Responsibility) 在 Servlet 规范里的经典实现;Spring Security 的 SecurityFilterChain 就是在这套机制上封装出来的应用。 Filter 接口 public interface Filter { default void init(FilterConfig filterConfig) throws ServletException { } void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; default void destroy() { } } init(FilterConfig):容器创建 Filter 实例后调用一次,用于读取初始化参数、保存 FilterConfig。 doFilter(request, response, chain):每次请求都会调用,是 Filter 的核心方法。 destroy():容器销毁 Filter 前调用一次,用于释放资源。 FilterConfig 提供访问 Filter 名称、初始化参数、ServletContext 的方法。 ...

Created 10106-06-10 · Updated 1016-07-01 · 2 min · 293 words · -

Forward 与 Redirect

forward vs redirect forward(请求转发):服务器收到请求后,在服务器内部把请求转交给另一个资源处理,再把结果返回客户端;浏览器地址栏不变,客户端不知道发生了转发。 redirect(重定向):服务器返回 3xx 状态码,浏览器再次发起新请求访问目标 URL,地址栏变为新地址;因此有两次往返,通常比 forward 开销大。 数据与作用域 forward:同一 HttpServletRequest 继续传递,request 属性、request 参数可带到目标资源;常用 request.getAttribute() 读取上一环节放入的数据。 redirect:浏览器发的是新请求,上一请求的 request 属性不会保留;URL 查询参数会随新请求带上。HttpSession 仍可通过 cookie 关联(session 级数据一般可用),但不要把「上一 request 的 attribute」误当成 redirect 后还能直接读。 效率:forward 仅在服务端处理,对客户端透明;redirect 多一次客户端往返,通常更慢。 范围:因 request.setAttribute() 的生命周期限于当前 request,redirect 会导致 attribute 丢失;需要跨 redirect 传值时,常用 session、URL 参数或 flash 等机制。 前后端分离下的表现 典型架构为 React 前端 + Spring Boot REST API。页面路由与组件组合由前端负责,后端主要返回 JSON;因此早年 JSP 时代「forward 到另一个 JSP 拼页面」的用法在业务层已基本消失,但两种机制仍以不同形式存在。 redirect:仍然常见 redirect 是 HTTP 层行为,与是否使用 JSP 无关。前后端分离项目中常见场景: OAuth / 第三方登录:授权服务器回调后,后端或网关返回 302 跳转到前端路由(如 /auth/callback) PRG(Post-Redirect-Get):表单或写操作后 return "redirect:/...",避免刷新重复提交(多见于仍保留 @Controller 的服务端表单) 文件下载、外链跳转:API 或网关返回 302 指向实际资源地址 网关 / 反向代理:未登录时重定向到登录页(也可由前端根据 401 自行跳转) 前端日常路由切换由 React Router 完成,不经过 Servlet redirect;但跨域认证、登录回调、下载等仍会碰到 HTTP 重定向。 ...

Created 21216-09-21 · Updated 21216-06-21 · 1 min · 206 words · -

Jetty

Jetty Jetty 是一个开源的 servlet 容器,它为基于 Java 的 web 内容(例如 JSP 和 servlet)提供运行环境。Jetty 使用 Java 编写,API 以一组 JAR 包的形式发布。开发人员可以将 Jetty 容器实例化成一个对象,为一些独立运行(stand-alone)的 Java 应用提供网络和 web 连接。 易用性 易用性是 Jetty 设计的基本原则,主要体现在: 通过 XML 或 API 配置 Jetty 默认配置可满足大部分需求 将 Jetty 嵌入应用程序只需很少的代码 可扩展性 在使用了 Ajax 的 Web 2.0 应用中,每个连接需要保持更长时间,线程和内存消耗会明显增加。Jetty 在这方面有优势: 即使在大量服务请求下,系统性能仍可保持可接受水平 利用 Continuation 机制处理大量用户请求及长连接 接口设计良好,当某种实现无法满足需求时,可方便地修改 Jetty 的特定实现 易嵌入性 Jetty 设计之初就是作为优秀组件来设计的,可非常容易地嵌入应用程序,无需为使用 Jetty 而大幅修改程序。某种程度上,也可以把 Jetty 理解为一个嵌入式 Web 服务器。 Jetty 可作为嵌入式服务器使用,运行速度较快且轻量,可在 Java 测试用例中控制其运行,使自动化测试不再依赖外部环境。 Jetty vs Tomcat 参考:Jetty 与 Tomcat 的比较(IBM developerWorks) ...

Created 16166-12-16 · Updated 20206-05-20 · 1 min · 173 words · -

Cypress vs Playwright: E2E 测试框架对比

概述 Cypress 和 Playwright 是目前最主流的两个 E2E(端到端)测试框架。两者都能模拟真实用户操作来测试 Web 应用,但在架构、能力和适用场景上有明显差异。 核心对比 维度 Cypress Playwright 开发商 Cypress.io Microsoft 首发年份 2017 2020 语言支持 JS / TS JS / TS / Python / Java / C# 浏览器支持 Chrome、Firefox、Edge、Electron Chrome、Firefox、Safari (WebKit)、Edge 移动端浏览器 不支持 支持(模拟移动设备) 多标签页 有限支持 原生支持 iframe 支持 受限 完整支持 并发执行 收费云服务 / 第三方插件 内置,免费 API 测试 支持 支持(更完整) 组件测试 成熟 实验性 架构差异 Cypress Cypress 运行在浏览器内部,测试代码与应用代码共享同一个 JavaScript 运行时。这一设计带来了极低的延迟和实时调试能力,但也造成了一些限制: 历史上不支持跨域(cross-origin)场景(v12 起已大幅改善) 同一时间只能操作一个标签页 不支持 Safari / WebKit Playwright Playwright 运行在浏览器外部,通过 Chrome DevTools Protocol(Chrome/Edge)和各浏览器原生协议(Firefox、WebKit)远程控制浏览器。这种架构更接近真实用户操作,且: ...

Created 11116-05-11 · Updated 11116-05-11 · 2 min · 244 words · -