mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-20 18:47:25 +08:00
重构
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
- [Session模型详解](/fun/session-model)
|
||||
- [TokenInfo参数详解](/fun/token-info)
|
||||
- [框架源码所有技术栈](/fun/tech-stack)
|
||||
- [Web开发常见漏洞防护](/fun/web-loophole)
|
||||
<!-- - [Sa-Token大事记](/fun/timeline) -->
|
||||
|
||||
|
||||
|
112
sa-token-doc/doc/fun/web-loophole.md
Normal file
112
sa-token-doc/doc/fun/web-loophole.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Web开发常见漏洞防护
|
||||
本章介绍web开发时常见漏洞的防护方法
|
||||
|
||||
|
||||
### 点击劫持
|
||||
|
||||
简而言之,点击劫持就是攻击者会自己搭建一个网页,这个网页分为两层:
|
||||
- 上层是被iframe导入的被攻击网站,具有一些敏感性操作,比如转账、点赞等按钮,这一层会完全透明
|
||||
- 下层是攻击者自己精心制作的网页,它会准备一个按钮诱导你进行点击(比如点击领取红包等),当你点击这个按钮时,响应你的将不会是这个按钮,而是上层的转账页面,在不知情的情况下造成财产损失
|
||||
|
||||
详情介绍参考:[https://blog.csdn.net/qq_32523587/article/details/79613768](https://blog.csdn.net/qq_32523587/article/details/79613768)
|
||||
|
||||
防范点击劫持的最有效做法就是增加响应头:`X-Frame-Options: DENY`, 告诉浏览器我们的网站不可以通过 iframe 进行展示(浏览器收到此响应头的指示之后,会拒绝渲染页面),
|
||||
从根本上杜绝了点击劫持发生的可能,在 [全局过滤器](/use/global-filter) 章节的示例中,我们已经展示了如何在过滤器中增加安全响应头
|
||||
|
||||
响应头`X-Frame-Options`有三个取值:
|
||||
- `DENY`: 任何时候都不可以通过 iframe 展示视图
|
||||
- `SAMEORIGIN`: 在同域下可以通过 iframe 展示视图
|
||||
- `ALLOW-FROM uri`: 指定地址来源的访问下可以通过 iframe 展示视图
|
||||
|
||||
除了后端的响应头,我们还可以在前端使用如下方式进行判断:
|
||||
``` js
|
||||
// 判断当前页面是否在顶层视口打开
|
||||
if(top != window) {
|
||||
// 跳入一个安全页面,比如404页
|
||||
location.href="xxx";
|
||||
}
|
||||
```
|
||||
除了跳转页面,你还可以用其它方法防御点击劫持,比如加载一个全局遮罩来隔离用户的点击操作,或者在非顶层窗口下拒绝提交token,使用户保持未登录状态
|
||||
|
||||
|
||||
### XSS攻击
|
||||
|
||||
XSS(跨站脚本攻击)就是指攻击者在一段正常的内容中嵌入恶意脚本,使得访问网页的用户自动运行一些破坏性的代码
|
||||
|
||||
例如一个论坛具有发帖功能,攻击者在发帖时故意插入一段如下内容:
|
||||
``` java
|
||||
<img src="xxx" onerror="alert('xss攻击!')" />
|
||||
```
|
||||
如果论坛服务端没有对此进行任何防护,那么用户每次访问这个帖子的时候都会被强制弹窗,
|
||||
事实上真正的`XSS攻击`绝不只是弹窗骚扰一下那么简单,它可以完成窃取Cookie,自动转账等破坏性操作
|
||||
|
||||
防范XSS攻击:
|
||||
1. 首先安全响应头给安排上:`X-Frame-Options: 1; mode=block`, 这是浏览器默认提供的XSS防护机制
|
||||
2. 有条件的情况下,尽量使用前后台分离架构,传统服务端渲染视图时几乎每一个变量都可能成为XSS注入点,而前后台分离下一般只有富文本渲染才会有机会XSS注入
|
||||
3. 对所有的用户输入必须XSS过滤,特别是字符串型参数
|
||||
4. 可以使用一些自动扫描工具寻找潜在的 XSS 漏洞
|
||||
|
||||
|
||||
### CSRF攻击
|
||||
CSRF(跨站请求伪造),又称 XSRF,攻击流程如下:
|
||||
|
||||
1. 用户登陆站点`a.com`,身份令牌被写入Cookie中
|
||||
2. 攻击者搭建站点`b.com`,引诱用户访问
|
||||
3. 用户访问`b.com`时,自动执行了攻击者准备的js代码,即:调用`a.com`的转账接口
|
||||
4. 用户在不知情的情况下,造成了财产损失
|
||||
|
||||
仅仅访问一个不安全的站点就让我们造成了财产损失?事实上,真正的CSRF攻击并没有这么简单,挡在攻击者第一道门槛便是`CORS同源策略`
|
||||
|
||||
同源策略限制了js在`b.com`中只能操作`b.com`的数据(`Cookie`、`localStorage`、`DOM`等),而无法直接操作`a.com`的数据。
|
||||
|
||||
这就导致一个结果:虽然在`b.com`可以调用`a.com`的转账接口,但是却无法携带用户储存在`a.com`的授权Cookie,对于`a.com`来讲,即使收到了浏览器发来的请求,
|
||||
也因为请求中没有携带token令牌,而无法识别调用者具体是谁,只能将其视为一次无效调用。
|
||||
|
||||
但是,请注意!这个小小的限制,虽然为用户提供了安全保护,却也为我们开发者造成了不小的困扰,特别是在前后端分离架构下,我们经常会遇到这个错误:
|
||||
|
||||

|
||||
|
||||
这就是导致无数前端后端互相撕逼的 —— 跨域!
|
||||
|
||||
浏览器在检测到你身处`b.com`却想要调用`a.com`的接口时,会率先发送一个`OPTIONS`预检请求,目的是为了询问`a.com`是否同意`b.com`发起的请求,
|
||||
在默认情况下,`a.com`收到一个陌生的第三方网站发来的请求,做出的回应肯定是:`不允许`, 浏览器收到回应就识相的关闭了请求,跨域请求失败
|
||||
|
||||
但是,有些开发者为了省事,直接设置了响应头: `Access-Control-Allow-Origin: *`,允许任何第三方网站的请求,这就给`CSRF攻击`留下了可乘之机
|
||||
|
||||
假设我们设置了只允许指定的网站跨域请求,就万事大吉了吗?并没有,攻击者仍可以通过抓包等手段得到我们的转账url,
|
||||
在`b.com`里,通过`open(url)`直接打开一个新的窗口调用转账接口,由于是属于打开新页面,浏览器连`OPTIONS`预检请求都不会发送,而是直接调用接口成功
|
||||
|
||||
此招无解吗?并不。由于它是属于打开新页面,这就导致调用接口时只能发送`get请求`,我们在设计接口时只需要遵守一个准则:`敏感接口一律post,禁止get调用`即可。
|
||||
|
||||
究其原因,导致`CSRF攻击`频频发生的原因是什么?是我们在跨域请求时,浏览器总是“自作聪明”的自动提交主站`Cookie`,
|
||||
在浏览器的不断更新中,Cookie的跨域规则变得愈发复杂,新手开发者及其容易绕的晕头转向,而同时`w3c`对`Cookie`规范的各种修修补补,又总是解决一个问题的同时暴露出其他的N多问题
|
||||
|
||||
既然Cookie机制如此难以驾驭,我们何不果断的放弃Cookie机制,改用`localStorage`机制存储会话token,这种方式轻松避免了`自动提交`带来的各种安全问题。
|
||||
事实上,`localStorage存储` + `header请求头提交`也是前后台分离趋势下的常见会话处理方案
|
||||
|
||||
篇幅有限,我们总结一下防范`CSRF攻击`要点
|
||||
|
||||
**在Cookie模式下**:
|
||||
1. 仅靠`CORS同源策略`无法彻底防范`CSRF攻击`,我们必须在后台建立`第三方域名白名单`,只有在白名单中的第三方域名才可以跨域调用我们的接口
|
||||
2. 涉及到数据增删改类型的接口,必须是`post`模式(或其它),严禁`get`模式,查询接口可以`get`
|
||||
3. 敏感操作增加验证码或者二次验证密码,减小被攻击的概率
|
||||
|
||||
**在 localStorage存储 + header请求头提交 模式下**:
|
||||
1. 在配置文件中,配置`is-read-cookie: false`,关闭Cookie模式,防止Sa-Token在登录时注入Cookie
|
||||
2. 同上,敏感操作增加验证码或者二次验证密码,减小被攻击的概率
|
||||
|
||||
有关CSRF攻防讲解的比较通透的一篇文章:[https://juejin.cn/post/6844903689702866952](https://juejin.cn/post/6844903689702866952)
|
||||
|
||||
|
||||
### Token泄露
|
||||
Token泄露一般发生在客户端,比如用户连接了不安全的WiFi导致通讯被监听,虽然此情形下token泄露的责任在于用户,但是我们还是有必要采取一定的措施使其损失降到最低
|
||||
1. 有条件上https的话一律https
|
||||
2. token有效期一定不能设置为永久,而且要尽量的短(but:为了不影响用户体验又不能设置特别的短,so: 7-30天是个比较合适的范围)
|
||||
3. 对敏感操作接口,增加密码二次校验(或手机验证码等)
|
||||
4. 用户更改密码后使其历史会话直接过期
|
||||
5. 有条件的情况下后台管理增加踢人下线功能,对已经泄露token的账号可以及时清理下线
|
||||
|
||||
|
||||
<br><br>
|
||||
更多类型漏洞连载中.... (欢迎提交pr)
|
||||
|
@@ -15,7 +15,7 @@
|
||||
<a href="/">
|
||||
<div class="logo-box">
|
||||
<img src="logo.png" title="logo" />
|
||||
<h1 class="logo-text">sa-token</h1>
|
||||
<h1 class="logo-text">Sa-Token</h1>
|
||||
</div>
|
||||
</a>
|
||||
<nav>
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
<script>
|
||||
var name = '<img style="width: 60px; height: 60px; vertical-align: middle;" src="logo.png" alt="logo" /> ';
|
||||
name += '<b style="font-size: 28px; vertical-align: middle;">sa-token</b> <sub>v1.17.0</sub>'
|
||||
name += '<b style="font-size: 28px; vertical-align: middle;">Sa-Token</b> <sub>v1.17.0</sub>'
|
||||
window.$docsify = {
|
||||
name: name, // 名字
|
||||
repo: 'https://github.com/dromara/sa-token', // github地址
|
||||
|
@@ -82,7 +82,7 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
|
||||
}
|
||||
|
||||
/* 代码行号盒子样式 */
|
||||
.code-line-box {list-style-type: none; border-right: 1px solid #000; position: absolute; top: 0; left: 0; width: 40px;}
|
||||
.code-line-box {list-style-type: none; border-right: 1px solid #000; position: absolute; top: 0; left: 0; width: 40px; user-select: none;}
|
||||
.code-line-box {padding: calc(1.5em + 1px) 0px !important; padding-bottom: calc(1.5em + 20px) !important; margin: 0px !important;}
|
||||
.code-line-box {line-height: inherit !important; background-color: #111; color: #aaa;font-weight: 400;font-size: 0.85em;text-align: center;}
|
||||
.code-line-box {font-family: source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace;}
|
||||
|
@@ -7,6 +7,11 @@
|
||||
|
||||
<table class="gzh-table" style="text-align: center;">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=MzA4MDMyODg4OQ==&mid=2649482871&idx=2&sn=b376585faaf814d9072af539efda68fe&send_time="/>
|
||||
<b>大侠学JAVA</b>
|
||||
<span>道阻且长,行则将至,专注分享JAVA领域的干货</span>
|
||||
</td>
|
||||
<td>
|
||||
<img src="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&size=102&__biz=Mzg2MDIxNjAzNg==&mid=2247485810&idx=1&sn=afd46d5924afbc1030a87b5d56265fdf&send_time="/>
|
||||
<b>Java大厂面试官</b>
|
||||
@@ -19,7 +24,6 @@
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Spring WebFlux 集成 Sa-Token 示例
|
||||
|
||||
WebFlux基于Reactor响应式模型开发,有着与标准ServletAPI完全不同的底层架构,因此要适配WebFlux, 必须提供与Reactor相关的整合实现,
|
||||
本篇将以WebFlux为例,展示sa-token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**
|
||||
本篇将以WebFlux为例,展示sa-token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**(Netty、Soul、Gateway等)
|
||||
|
||||
整合示例在官方仓库的`/sa-token-demo-webflux`文件夹下,如遇到难点可结合源码进行测试学习
|
||||
|
||||
|
@@ -35,13 +35,10 @@ public class SaTokenConfigure {
|
||||
public SaServletFilter getSaReactorFilter() {
|
||||
return new SaServletFilter()
|
||||
|
||||
// 指定 [拦截路由]
|
||||
.addInclude("/**")
|
||||
// 指定 拦截路由 与 放行路由
|
||||
.addInclude("/**").addExclude("/favicon.ico")
|
||||
|
||||
// 指定 [放行路由]
|
||||
.addExclude("/favicon.ico")
|
||||
|
||||
// 指定[认证函数]: 每次请求执行
|
||||
// 认证函数: 每次请求执行
|
||||
.setAuth(r -> {
|
||||
System.out.println("---------- 进入sa-token全局认证 -----------");
|
||||
|
||||
@@ -51,11 +48,26 @@ public class SaTokenConfigure {
|
||||
// 更多拦截处理方式,请参考“路由拦截式鉴权”章节
|
||||
})
|
||||
|
||||
// 指定[异常处理函数]:每次[认证函数]发生异常时执行此函数
|
||||
// 异常处理函数:每次认证函数发生异常时执行此函数
|
||||
.setError(e -> {
|
||||
System.out.println("---------- 进入sa-token异常处理 -----------");
|
||||
return AjaxJson.getError(e.getMessage());
|
||||
})
|
||||
|
||||
// 前置函数:在每次认证函数之前执行
|
||||
.setBeforeAuth(r -> {
|
||||
// ---------- 设置一些安全响应头 ----------
|
||||
SaHolder.getResponse()
|
||||
// 服务器名称
|
||||
.setServer("sa-server")
|
||||
// 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
|
||||
.setHeader("X-Frame-Options", "SAMEORIGIN")
|
||||
// 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
|
||||
.setHeader("X-Frame-Options", "1; mode=block")
|
||||
// 禁用浏览器内容嗅探
|
||||
.setHeader("X-Content-Type-Options", "nosniff")
|
||||
;
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -117,6 +117,29 @@ StpUtil.checkRoleOr("super-admin", "shop-admin");
|
||||
你可以创建一个全局异常拦截器,统一返回给前端的格式,参考:[码云:GlobalException.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo-springboot/src/main/java/com/pj/test/GlobalException.java)
|
||||
|
||||
|
||||
### 权限通配符
|
||||
Sa-Token允许你根据通配符指定泛权限,例如当一个账号拥有`user*`的权限时,`user-add`、`user-delete`、`user-update`都将匹配通过
|
||||
|
||||
``` java
|
||||
// 当拥有 user* 权限时
|
||||
StpUtil.hasPermission("user-add"); // true
|
||||
StpUtil.hasPermission("user-update"); // true
|
||||
StpUtil.hasPermission("art-add"); // false
|
||||
|
||||
// 当拥有 *-delete 权限时
|
||||
StpUtil.hasPermission("user-add"); // false
|
||||
StpUtil.hasPermission("user-delete"); // true
|
||||
StpUtil.hasPermission("art-delete"); // true
|
||||
|
||||
// 当拥有 *.js 权限时
|
||||
StpUtil.hasPermission("index.js"); // true
|
||||
StpUtil.hasPermission("index.css"); // false
|
||||
StpUtil.hasPermission("index.html"); // false
|
||||
```
|
||||
|
||||
上帝权限:当一个账号拥有 `"*"` 权限时,他可以验证通过任何权限码 (角色认证同理)
|
||||
|
||||
|
||||
### 如何把权限精确搭到按钮级?
|
||||
权限精确到按钮级的意思就是指:**权限范围可以控制到页面上的每一个按钮是否显示**
|
||||
|
||||
|
Reference in New Issue
Block a user