From efbc582a049904390bfc9418560843813241ec6d Mon Sep 17 00:00:00 2001
From: ChenTao-Ji
Date: Fri, 27 Sep 2019 16:20:56 +0800
Subject: [PATCH 01/13] =?UTF-8?q?Update=20=E6=95=B0=E6=8D=AE=E7=BB=93?=
=?UTF-8?q?=E6=9E=84.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Set集合子类HashSet与TreeSet去除重复实现。
---
.../\346\225\260\346\215\256\347\273\223\346\236\204.md" | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git "a/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md"
index 2632a9e2183..dfb5bc18586 100644
--- "a/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md"
+++ "b/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md"
@@ -47,7 +47,7 @@ Queue 用来存放 等待处理元素 的集合,这种场景一般用于缓冲
### 什么是 Set
Set 继承于 Collection 接口,是一个不允许出现重复元素,并且无序的集合,主要 HashSet 和 TreeSet 两大实现类。
-在判断重复元素的时候,Set 集合会调用 hashCode()和 equal()方法来实现。
+在判断重复元素的时候,HashSet 集合会调用 hashCode()和 equal()方法来实现;TreeSet 集合会调用compareTo方法来实现。
### 补充:有序集合与无序集合说明
- 有序集合:集合里的元素可以根据 key 或 index 访问 (List、Map)
From c67a99c9c6e26362ca736802bfad3a1349b5cd83 Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Mon, 30 Sep 2019 10:23:47 +0800
Subject: [PATCH 02/13] Update README.md
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index df57797c35c..78f7716aea2 100644
--- a/README.md
+++ b/README.md
@@ -162,7 +162,6 @@
- [SpringMVC 工作原理详解](docs/system-design/framework/spring/SpringMVC-Principle.md)
- [Spring中都用到了那些设计模式?](docs/system-design/framework/spring/Spring-Design-Patterns.md)
- [SpringBoot 使用指南](https://github.com/Snailclimb/springboot-guide)
--
#### ZooKeeper
From f3b8ab708233f3926c3c44f48a481bde5702ae5f Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Wed, 2 Oct 2019 16:49:12 +0800
Subject: [PATCH 03/13] =?UTF-8?q?=E5=B0=86=E9=87=8D=E8=A6=81=E7=9A=84?=
=?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=86=85=E5=AE=B9=E5=8A=A0=E7=B2=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 47 ++++++++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index 78f7716aea2..65441ecdf00 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@
- [MySQL](#mysql)
- [Redis](#redis)
- [系统设计](#系统设计)
- - [常用框架(Spring、Zookeeper ... )](#常用框架)
+ - [常用框架(Spring/SpringBoot、Zookeeper ... )](#常用框架)
- [权限认证](#权限认证)
- [设计模式(工厂模式、单例模式 ... )](#设计模式)
- [数据通信(消息队列、Dubbo ... )](#数据通信)
@@ -60,22 +60,22 @@
### 基础
-* [Java 基础知识回顾](docs/java/Java基础知识.md)
-* [Java 基础知识疑难点/易错点](docs/java/Java疑难点.md)
-* [一些重要的Java程序设计题](docs/java/Java程序设计题.md)
+* **[Java 基础知识回顾](docs/java/Java基础知识.md)**
+* **[Java 基础知识疑难点/易错点](docs/java/Java疑难点.md)**
+* **[一些重要的Java程序设计题](docs/java/Java程序设计题.md)**
* [J2EE 基础知识回顾](docs/java/J2EE基础知识.md)
### 容器
-* [Java容器常见面试题/知识点总结](docs/java/collection/Java集合框架常见面试题.md)
+* **[Java容器常见面试题/知识点总结](docs/java/collection/Java集合框架常见面试题.md)**
* [ArrayList 源码学习](docs/java/collection/ArrayList.md)
* [LinkedList 源码学习](docs/java/collection/LinkedList.md)
* [HashMap(JDK1.8)源码学习](docs/java/collection/HashMap.md)
### 并发
-* [Java 并发基础常见面试题总结](docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md)
-* [Java 并发进阶常见面试题总结](docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md)
+* **[Java 并发基础常见面试题总结](docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md)**
+* **[Java 并发进阶常见面试题总结](docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md)**
* [并发容器总结](docs/java/Multithread/并发容器总结.md)
* [乐观锁与悲观锁](docs/essential-content-for-interview/面试必备之乐观锁与悲观锁.md)
* [JUC 中的 Atomic 原子类总结](docs/java/Multithread/Atomic.md)
@@ -83,11 +83,11 @@
### JVM
-* [一 Java内存区域](docs/java/jvm/Java内存区域.md)
-* [二 JVM垃圾回收](docs/java/jvm/JVM垃圾回收.md)
+* **[一 Java内存区域](docs/java/jvm/Java内存区域.md)**
+* **[二 JVM垃圾回收](docs/java/jvm/JVM垃圾回收.md)**
* [三 JDK 监控和故障处理工具](docs/java/jvm/JDK监控和故障处理工具总结.md)
* [四 类文件结构](docs/java/jvm/类文件结构.md)
-* [五 类加载过程](docs/java/jvm/类加载过程.md)
+* **[五 类加载过程](docs/java/jvm/类加载过程.md)**
* [六 类加载器](docs/java/jvm/类加载器.md)
### I/O
@@ -137,8 +137,8 @@
### MySQL
-* [MySQL 学习与面试](docs/database/MySQL.md)
-* [一千行MySQL学习笔记](docs/database/一千行MySQL命令.md)
+* **[MySQL 学习与面试](docs/database/MySQL.md)**
+* **[一千行MySQL学习笔记](docs/database/一千行MySQL命令.md)**
* [MySQL高性能优化规范建议](docs/database/MySQL高性能优化规范建议.md)
* [数据库索引总结](docs/database/MySQL%20Index.md)
* [事务隔离级别(图文详解)](docs/database/事务隔离级别(图文详解).md)
@@ -154,14 +154,14 @@
### 常用框架
-#### Spring
+#### Spring/SpringBoot
- [Spring 学习与面试](docs/system-design/framework/spring/Spring.md)
-- [Spring 常见问题总结](docs/system-design/framework/spring/SpringInterviewQuestions.md)
+- **[Spring 常见问题总结](docs/system-design/framework/spring/SpringInterviewQuestions.md)**
+- **[SpringBoot 指南/常见面试题总结](https://github.com/Snailclimb/springboot-guide)**
- [Spring中bean的作用域与生命周期](docs/system-design/framework/spring/SpringBean.md)
- [SpringMVC 工作原理详解](docs/system-design/framework/spring/SpringMVC-Principle.md)
- [Spring中都用到了那些设计模式?](docs/system-design/framework/spring/Spring-Design-Patterns.md)
-- [SpringBoot 使用指南](https://github.com/Snailclimb/springboot-guide)
#### ZooKeeper
@@ -170,8 +170,8 @@
### 权限认证
-- [权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)
-- [适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)
+- **[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)**
+- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)**
### 设计模式
@@ -196,12 +196,12 @@
### 备战面试
-* [【备战面试1】程序员的简历就该这样写](docs/essential-content-for-interview/PreparingForInterview/程序员的简历之道.md)
-* [【备战面试2】初出茅庐的程序员该如何准备面试?](docs/essential-content-for-interview/PreparingForInterview/interviewPrepare.md)
-* [【备战面试3】7个大部分程序员在面试前很关心的问题](docs/essential-content-for-interview/PreparingForInterview/JavaProgrammerNeedKnow.md)
-* [【备战面试4】Github上开源的Java面试/学习相关的仓库推荐](docs/essential-content-for-interview/PreparingForInterview/JavaInterviewLibrary.md)
-* [【备战面试5】如果面试官问你“你有什么问题问我吗?”时,你该如何回答](docs/essential-content-for-interview/PreparingForInterview/如果面试官问你“你有什么问题问我吗?”时,你该如何回答.md)
-* [【备战面试6】美团面试常见问题总结(附详解答案)](docs/essential-content-for-interview/PreparingForInterview/美团面试常见问题总结.md)
+* **[【备战面试1】程序员的简历就该这样写](docs/essential-content-for-interview/PreparingForInterview/程序员的简历之道.md)**
+* **[【备战面试2】初出茅庐的程序员该如何准备面试?](docs/essential-content-for-interview/PreparingForInterview/interviewPrepare.md)**
+* **[【备战面试3】7个大部分程序员在面试前很关心的问题](docs/essential-content-for-interview/PreparingForInterview/JavaProgrammerNeedKnow.md)**
+* **[【备战面试4】Github上开源的Java面试/学习相关的仓库推荐](docs/essential-content-for-interview/PreparingForInterview/JavaInterviewLibrary.md)**
+* **[【备战面试5】如果面试官问你“你有什么问题问我吗?”时,你该如何回答](docs/essential-content-for-interview/PreparingForInterview/如果面试官问你"你有什么问题问我吗?"时,你该如何回答.md)**
+* **[【备战面试6】美团面试常见问题总结(附详解答案)](docs/essential-content-for-interview/PreparingForInterview/美团面试常见问题总结.md)**
### 常见面试题总结
@@ -236,6 +236,7 @@
### 实战项目推荐
- [onemall](https://github.com/YunaiV/onemall) : mall 商城,基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。
+-
### Github 历史榜单
From e5ed295760ba8aa9771c4ab27be4a55de1192dda Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Wed, 2 Oct 2019 22:52:47 +0800
Subject: [PATCH 04/13] Update _coverpage.md
---
docs/_coverpage.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index 612cd2160ec..730241144c6 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -3,7 +3,6 @@
Java 学习/面试指南
-
[常用资源](https://shimo.im/docs/MuiACIg1HlYfVxrj/)
[GitHub]()
[开始阅读](#java)
From 1013e57fee2a910e1bb362f5c716083d0b1ef34c Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Wed, 2 Oct 2019 23:12:22 +0800
Subject: [PATCH 05/13] Update _coverpage.md
---
docs/_coverpage.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index 730241144c6..612cd2160ec 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -3,6 +3,7 @@
Java 学习/面试指南
+
[常用资源](https://shimo.im/docs/MuiACIg1HlYfVxrj/)
[GitHub]()
[开始阅读](#java)
From bff6774dc76e4204d923dbfc69f36a96bf9b56a7 Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Wed, 2 Oct 2019 23:12:26 +0800
Subject: [PATCH 06/13] Update README.md
---
README.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/README.md b/README.md
index 65441ecdf00..0d1c7d5c0dd 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-点击订阅[Java面试进阶指南](https://xiaozhuanlan.com/javainterview?rel=javaguide)(专为Java面试方向准备)。[为什么要弄这个专栏?](https://shimo.im/docs/9BJjNsNg7S4dCnz3/)
-
点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
From 18f3c4616e8f8d9b0e5ae30f325ed4cd8338a25a Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Wed, 2 Oct 2019 23:53:09 +0800
Subject: [PATCH 07/13] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 0d1c7d5c0dd..73df6a77f8c 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
+
推荐使用 https://snailclimb.top/JavaGuide/ 在线阅读(访问速度慢的话,请使用 https://snailclimb.gitee.io/javaguide ),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
From 2cd46a04f2025db9ef36e8c4e5ec4f3c90702ddb Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 3 Oct 2019 10:07:49 +0800
Subject: [PATCH 08/13] Update README.md
---
README.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/README.md b/README.md
index 73df6a77f8c..55eae603d23 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,11 @@
点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
+作者的其他开源项目推荐:
+
+1. [springboot-guide](https://github.com/Snailclimb/springboot-guide) : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维护)。
+2. [programmer-advancement](https://github.com/Snailclimb/programmer-advancement) : 我觉得技术人员应该有的一些好习惯!
+3. [spring-security-jwt-guide](https://github.com/Snailclimb/spring-security-jwt-guide) :从零入门 !Spring Security With JWT(含权限验证)后端部分代码。
+
From 8bad2674bbe28de9f4be75a49a05e36e4cccf357 Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Mon, 7 Oct 2019 12:44:29 +0800
Subject: [PATCH 09/13] =?UTF-8?q?Create=20JWT=E4=BC=98=E5=8A=A3=E5=8A=BF?=
=?UTF-8?q?=E5=88=86=E6=9E=90.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...43\345\212\277\345\210\206\346\236\220.md" | 85 +++++++++++++++++++
1 file changed, 85 insertions(+)
create mode 100644 "docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md"
diff --git "a/docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md" "b/docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md"
new file mode 100644
index 00000000000..c5c7f51a063
--- /dev/null
+++ "b/docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md"
@@ -0,0 +1,85 @@
+# JWT 优缺点分析以及常见问题解决方案
+
+## Token 认证的优势
+
+ 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势:
+
+### 1.无状态
+
+token 自身包含了身份验证所需要的所有信息,使得我们的服务器不需要存储 Session 信息,这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。但是,也正是由于 token 的无状态,也导致了它最大的缺点:当后端 在token 有效期内废弃一个 token 或者更改它的权限的话,不会立即生效,一般需要等到有效期过后才可以。另外,当用户 Logout 的话,token 也还有效。除非,我们在后端增加额外的处理逻辑。
+
+### 2.有效避免了CSRF 攻击
+
+**CSRF(Cross Site Request Forgery)**一般被翻译为 **跨站请求伪造**,属于网络攻击领域范围。相比于 SQL 脚本注入、XSS等等安全攻击方式,CSRF 的知名度并没有它们高。但是,它的确是每个系统都要考虑的安全隐患,就连技术帝国 Google 的 Gmail 在早些年也被曝出过存在 CSRF 漏洞,这给 Gmail 的用户造成了很大的损失。
+
+那么究竟什么是 **跨站请求伪造** 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子:
+
+小壮登录了某网上银行,它来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
+
+```html
+科学理财,年盈利率过万>
+```
+
+导致这个问题很大的愿意就是: Session 认证中 Cookie 中的 session_id 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
+
+**那为什么 token 不会存在这种问题呢?**
+
+我是这样理解的:一般情况下我们使用 JWT 的话,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。
+
+但是这样会存在 XSS 攻击中被盗的风险,为了避免 XSS 攻击,你可以选择将 token 存储在标记为`httpOnly` 的cookie 中。但是,这样有导致了你必须自己提供CSRF保护。
+
+具体采用上面哪两种方式存储 token 呢,大部分情况下存放在 local storage 下都是最好的选择,某些情况下可能需要存放在标记为`httpOnly` 的cookie 中会更好。
+
+### 3.适合移动端应用
+
+使用 Session 进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到 Cookie(需要 Cookie 保存 SessionId),所以不适合移动端。
+
+但是,使用 token 进行身份认证就不会存在这种问题,因为只要 token 可以被客户端存储就能够使用,而且 token 还可以跨语言使用。
+
+### 4.单点登录友好
+
+使用 Session 进行身份认证的话,实现单点登录,需要我们把用户的 Session 信息保存在一台电脑上,并且还会遇到常见的 Cookie 跨域的问题。但是,使用 token 进行认证的话, token 被保存在客户端,不会存在这些问题。
+
+## Token 认证常见问题以及解决办法
+
+### 1.注销登录等场景下 token 还有效
+
+与之类似的具体相关场景有:
+
+1. 退出登录;
+2. 修改密码;
+3. 服务端修改了某个用户具有的权限或者角色;
+4. 用户的帐户被删除/暂停。
+5. 用户由管理员注销;
+
+这个问题不存在于 Session 认证方式中,因为在 Session 认证方式中,遇到这种情况的话服务端删除对应的 Session 记录即可。但是,使用 token 认证的方式就不好解决了。我们也说过了,token 一旦派发出去,如果后端不增加其他逻辑的话,它在失效之前都是有效的。那么,我们如何解决这个问题呢?查阅了很多资料,总结了下面几种方案:
+
+- **将 token 存入内存数据库**:将 token 存入 DB 中,redis 内存数据库在这里是是不错的选择。如果需要让某个 token 失效就直接从 redis 中删除这个 token 即可。但是,这样会导致每次使用 token 发送请求都要先从 DB 中查询 token 是否存在的步骤,而且违背了 JWT 的无状态原则。
+- **黑名单机制**:和上面的方式类似,使用内存数据库比如 redis 维护一个黑名单,如果想让某个 token 失效的话就直接将这个 token 加入到 **黑名单** 即可。然后,每次使用 token 进行请求的话都会先判断这个 token 是否存在于黑名单中。
+- **修改密钥 (Secret)** : 我们为每个用户都创建一个专属密钥,如果我们想让某个 token 失效,我们直接修改对应用户的密钥即可。但是,这样相比于前两种引入内存数据库带来了危害更大,比如:1⃣️如果服务是分布式的,则每次发出新的 token 时都必须在多台机器同步密钥。为此,你需要将必须将机密存储在数据库或其他外部服务中,这样和 Session 认证就没太大区别了。2⃣️如果用户同时在两个浏览器打开系统,或者在手机端也打开了系统,如果它从一个地方将账号退出,那么其他地方都要重新进行登录,这是不可取的。
+- **保持令牌的有效期限短并经常轮换** :很简单的一种方式。但是,会导致用户登录状态不会被持久记录,而且需要用户经常登录。
+
+对于修改密码后 token 还有效问题的解决还是比较容易的,说一种我觉得比较好的方式:**使用用户的密码的哈希值对 token 进行签名。因此,如果密码更改,则任何先前的令牌将自动无法验证。**
+
+### 2.token 的续签问题
+
+token 有效期一般都建议设置的不太长,那么 token 过期后如何认证,如何实现动态刷新 token,避免用户经常需要重新登录?
+
+我们先来看看在 Session 认证中一般的做法:**假如 session 的有效期30分钟,如果 30 分钟内用户有访问,就把 session 有效期被延长30分钟。**
+
+1. **类似于 Session 认证中的做法**:这种方案满足于大部分场景。假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,如果发现 token 的有效期马上快过期了,服务端就重新生成 token 给客户端。客户端每次请求都检查新旧token,如果不一致,则更新本地的token。这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。
+2. **每次请求都返回新 token** :这种方案的的思路很简单,但是,很明显,开销会比较大。
+3. **token 有效期设置到半夜** :这种方案是一种折衷的方案,保证了大部分用户白天可以正常登录,适用于对安全性要求不高的系统。
+4. **用户登录返回两个 token** :第一个是 acessToken ,它的过期时间 token 本身的过期时间比如半个小时,另外一个是 refreshToken 它的过期时间更长一点比如为1天。客户端登录后,将 accessToken和refreshToken 保存在本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,如果过期的话,就将 refreshToken 传给服务端。如果有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。该方案的不足是:1⃣️需要客户端来配合;2⃣️用户注销的时候需要同时保证两个 token 都无效;3⃣️重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,提前去通过 refreshToken 获取新的accessToken)。
+
+## 总结
+
+JWT 最适合的场景是无状态的场景,如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。
+
+## Reference
+
+- https://medium.com/devgorilla/how-to-log-out-when-using-jwt-a8c7823e8a6
+- [JWT 超详细分析](https://learnku.com/articles/17883?order_by=vote_count&)
+- https://medium.com/@agungsantoso/csrf-protection-with-json-web-tokens-83e0f2fcbcc
+- [Invalidating JSON Web Tokens](https://stackoverflow.com/questions/21978658/invalidating-json-web-tokens)
+
From b1bda0762bf09cd4286c1a3d3ffcdb07d0361117 Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Mon, 7 Oct 2019 12:46:44 +0800
Subject: [PATCH 10/13] =?UTF-8?q?JWT=20=E4=BC=98=E5=8A=A3=E5=8A=BF?=
=?UTF-8?q?=E5=88=86=E6=9E=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 1 +
.../authority-certification/JWT-advantages-and-disadvantages.md | 0
2 files changed, 1 insertion(+)
rename "docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md" => docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md (100%)
diff --git a/README.md b/README.md
index 55eae603d23..f93391c231b 100644
--- a/README.md
+++ b/README.md
@@ -176,6 +176,7 @@
### 权限认证
- **[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)**
+- **[JWT 优劣势分析](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)**
- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)**
### 设计模式
diff --git "a/docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md" b/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
similarity index 100%
rename from "docs/system-design/authority-certification/JWT\344\274\230\345\212\243\345\212\277\345\210\206\346\236\220.md"
rename to docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
From 9ceb6ea385460b3df2ef910e16222ae0c9557510 Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Mon, 7 Oct 2019 12:47:35 +0800
Subject: [PATCH 11/13] Update JWT-advantages-and-disadvantages.md
---
.../authority-certification/JWT-advantages-and-disadvantages.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md b/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
index c5c7f51a063..076666af73c 100644
--- a/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
+++ b/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
@@ -78,8 +78,8 @@ JWT 最适合的场景是无状态的场景,如果考虑到 token 注销和 to
## Reference
+- [JWT 超详细分析](https://learnku.com/articles/17883?order_by=vote_count&)
- https://medium.com/devgorilla/how-to-log-out-when-using-jwt-a8c7823e8a6
-- [JWT 超详细分析](https://learnku.com/articles/17883?order_by=vote_count&)
- https://medium.com/@agungsantoso/csrf-protection-with-json-web-tokens-83e0f2fcbcc
- [Invalidating JSON Web Tokens](https://stackoverflow.com/questions/21978658/invalidating-json-web-tokens)
From 39c4a8299f7a7cd2d92b760b792372f1c112b5cb Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Mon, 7 Oct 2019 12:48:16 +0800
Subject: [PATCH 12/13] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index f93391c231b..21a458b0480 100644
--- a/README.md
+++ b/README.md
@@ -176,7 +176,7 @@
### 权限认证
- **[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](docs/system-design/authority-certification/basis-of-authority-certification.md)**
-- **[JWT 优劣势分析](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)**
+- **[JWT 优缺点分析以及常见问题解决方案](docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md)**
- **[适合初学者入门 Spring Security With JWT 的 Demo](https://github.com/Snailclimb/spring-security-jwt-guide)**
### 设计模式
From 403937c0575e57e5a7d3c3bae159b105bbcbdafa Mon Sep 17 00:00:00 2001
From: Kou Shuang
Date: Tue, 8 Oct 2019 21:05:51 +0800
Subject: [PATCH 13/13] Update JWT-advantages-and-disadvantages.md
---
.../JWT-advantages-and-disadvantages.md | 20 +++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md b/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
index 076666af73c..4d16c413727 100644
--- a/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
+++ b/docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md
@@ -1,4 +1,12 @@
-# JWT 优缺点分析以及常见问题解决方案
+# JWT 身份认证优缺点分析以及常见问题解决方案
+
+之前分享了一个使用 Spring Security 实现 JWT 身份认证的 Demo,文章地址:[适合初学者入门 Spring Security With JWT 的 Demo](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485622&idx=1&sn=e9750ed63c47457ba1896db8dfceac6a&chksm=cea2477df9d5ce6b7af20e582c6c60b7408a6459b05b849394c45f04664d1651510bdee029f7&token=684071313&lang=zh_CN&scene=21#wechat_redirect)。 Demo 非常简单,没有介绍到 JWT 存在的一些问题。所以,单独抽了一篇文章出来介绍。为了完成这篇文章,我查阅了很多资料和文献,我觉得应该对大家有帮助。
+
+相关阅读:
+
+- [《一问带你区分清楚Authentication,Authorization以及Cookie、Session、Token》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485626&idx=1&sn=3247aa9000693dd692de8a04ccffeec1&chksm=cea24771f9d5ce675ea0203633a95b68bfe412dc6a9d05f22d221161147b76161d1b470d54b3&token=684071313&lang=zh_CN&scene=21#wechat_redirect)
+- [适合初学者入门 Spring Security With JWT 的 Demo](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485622&idx=1&sn=e9750ed63c47457ba1896db8dfceac6a&chksm=cea2477df9d5ce6b7af20e582c6c60b7408a6459b05b849394c45f04664d1651510bdee029f7&token=684071313&lang=zh_CN&scene=21#wechat_redirect)
+- [Spring Boot 使用 JWT 进行身份和权限验证](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485640&idx=1&sn=0ff147808318d53b371f16bb730c96ef&chksm=cea24703f9d5ce156ba67662f6f3f482330e8e6ebd9d44c61bf623083e9b941d8a180db6b0ea&token=1533246333&lang=zh_CN#rd)
## Token 认证的优势
@@ -6,7 +14,7 @@
### 1.无状态
-token 自身包含了身份验证所需要的所有信息,使得我们的服务器不需要存储 Session 信息,这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。但是,也正是由于 token 的无状态,也导致了它最大的缺点:当后端 在token 有效期内废弃一个 token 或者更改它的权限的话,不会立即生效,一般需要等到有效期过后才可以。另外,当用户 Logout 的话,token 也还有效。除非,我们在后端增加额外的处理逻辑。
+token 自身包含了身份验证所需要的所有信息,使得我们的服务器不需要存储 Session 信息,这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。但是,也正是由于 token 的无状态,也导致了它最大的缺点:当后端在token 有效期内废弃一个 token 或者更改它的权限的话,不会立即生效,一般需要等到有效期过后才可以。另外,当用户 Logout 的话,token 也还有效。除非,我们在后端增加额外的处理逻辑。
### 2.有效避免了CSRF 攻击
@@ -14,19 +22,19 @@ token 自身包含了身份验证所需要的所有信息,使得我们的服
那么究竟什么是 **跨站请求伪造** 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子:
-小壮登录了某网上银行,它来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
+小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
```html
科学理财,年盈利率过万>
```
-导致这个问题很大的愿意就是: Session 认证中 Cookie 中的 session_id 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
+导致这个问题很大的原因就是: Session 认证中 Cookie 中的 session_id 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
**那为什么 token 不会存在这种问题呢?**
我是这样理解的:一般情况下我们使用 JWT 的话,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。
-但是这样会存在 XSS 攻击中被盗的风险,为了避免 XSS 攻击,你可以选择将 token 存储在标记为`httpOnly` 的cookie 中。但是,这样有导致了你必须自己提供CSRF保护。
+但是这样会存在 XSS 攻击中被盗的风险,为了避免 XSS 攻击,你可以选择将 token 存储在标记为`httpOnly` 的cookie 中。但是,这样又导致了你必须自己提供CSRF保护。
具体采用上面哪两种方式存储 token 呢,大部分情况下存放在 local storage 下都是最好的选择,某些情况下可能需要存放在标记为`httpOnly` 的cookie 中会更好。
@@ -74,7 +82,7 @@ token 有效期一般都建议设置的不太长,那么 token 过期后如何
## 总结
-JWT 最适合的场景是无状态的场景,如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。
+JWT 最适合的场景是不需要服务端保存用户状态的场景,比如如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。
## Reference