1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-25 02:27:10 +08:00

[docs]jvm

This commit is contained in:
guide 2021-06-07 10:46:10 +08:00
parent 0af6c51134
commit e2e340c7cb
3 changed files with 132 additions and 76 deletions

View File

@ -78,6 +78,8 @@
### JVM (必看 :+1:)
JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle.com/javase/specs/jvms/se8/html/index.html) 和周志明老师的[《深入理解Java虚拟机第3版](https://book.douban.com/subject/34907497/) (强烈建议阅读多遍!)。
1. **[Java 内存区域](docs/java/jvm/Java内存区域.md)**
2. **[JVM 垃圾回收](docs/java/jvm/JVM垃圾回收.md)**
3. [JDK 监控和故障处理工具](docs/java/jvm/JDK监控和故障处理工具总结.md)

View File

@ -26,6 +26,10 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png)
详见:[jvm规范5.4](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4) 。
![](https://img-blog.csdnimg.cn/20210607102244508.png)
### 加载
类加载过程的第一步,主要完成下面 3 件事情:

View File

@ -1,45 +1,75 @@
## 1. 认证 (Authentication) 和授权 (Authorization)的区别是什么?
## 认证 (Authentication) 和授权 (Authorization)的区别是什么?
这是一个绝大多数人都会混淆的问题。首先先从读音上来认识这两个名词,很多人都会把它俩的读音搞混,所以我建议你先先去查一查这两个单词到底该怎么读,他们的具体含义是什么。
说简单点就是:
**认证 (Authentication)** 你是谁。
![](./images/basis-of-authority-certification/authentication.png)
**授权 (Authorization)** 你有权限干什么。
![](./images/basis-of-authority-certification/authorization.png)
- **认证 (Authentication)** 你是谁。
- **授权 (Authorization)** 你有权限干什么。
稍微正式点(啰嗦点)的说法就是
- **Authentication认证** 是验证您的身份的凭据(例如用户名/用户 ID 和密码通过这个凭据系统得以知道你就是你也就是说系统存在你这个用户。所以Authentication 被称为身份/用户验证。
- **Authorization授权** 发生在 **Authentication认证** 之后。授权嘛,光看意思大家应该就明白,它主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如 admin有些对系统资源操作比如删除、添加、更新只能特定人才具有。
认证
![](https://img-blog.csdnimg.cn/20210604160908352.png)
授权:
![](https://img-blog.csdnimg.cn/20210604161032412.png)
这两个一般在我们的系统中被结合在一起使用,目的就是为了保护我们系统的安全性。
## 2. 什么是Cookie ? Cookie的作用是什么?如何在服务端使用 Cookie ?
## RBAC 模型介绍一下?
![](./images/basis-of-authority-certification/cookie-sessionId.png)
系统权限控制最常采用的访问控制模型就是 **RBAC 模型**
### 2.1 什么是Cookie ? Cookie的作用是什么?
**什么是 RBAC 呢?**
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式但是两者的应用场景不太一样
RBAC 即基于角色的权限访问控制Role-Based Access Control。这是一种通过角色关联权限角色同时又关联用户的授权的方式
维基百科是这样定义 Cookie 的Cookies是某些网站为了辨别用户身份而储存在用户本地终端上的数据通常经过加密。简单来说 **Cookie 存放在客户端,一般用来保存用户信息**
简单地说:一个用户可以拥有若干角色,每一个角色有可以被分配若干权限这样,就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图
下面是 Cookie 的一些应用案例:
![RBAC](https://cdn.jsdelivr.net/gh/javaguide-tech/blog-images-3@main/11-9/RBAC.png)
1. 我们在 Cookie 中保存已经登录过的用户信息下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外Cookie 还能保存用户首选项,主题和其他设置信息。
2. 使用Cookie 保存 session 或者 token ,向后端发送请求的时候带上 Cookie这样后端就能取到session或者token了。这样就能记录用户当前的状态了因为 HTTP 协议是无状态的。
3. Cookie 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候因为HTTP协议是没有状态的如果服务器想要获取你在某个页面的停留状态或者看了哪些商品一种常用的实现方式就是将这些信息存放在Cookie
**在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。**
### 2.2 如何在服务端使用 Cookie 呢?
本系统的权限设计相关的表如下(一共 5 张表2 张用户建立表之间的联系):
这部分内容参考https://attacomsian.com/blog/cookies-spring-boot, 更多如何在Spring Boot中使用Cookie 的内容可以查看这篇文章。
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-11/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BE%E8%AE%A1-%E6%9D%83%E9%99%90.png)
**1)设置cookie返回给客户端**
通过这个权限模型,我们可以创建不同的角色并为不同的角色分配不同的权限范围(菜单)。
![](https://cdn.jsdelivr.net/gh/javaguide-tech/blog-images-3@main/11-7/%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97.png)
通常来说,如果系统对于权限控制要求比较严格的话,一般都会选择使用 RBAC 模型来做权限控制。
## 什么是 Cookie ? Cookie 的作用是什么?
![](./images/basis-of-authority-certification/cookie-SessionId.png)
`Cookie``Session` 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
维基百科是这样定义 `Cookie` 的:
> `Cookies` 是某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。
简单来说: **`Cookie` 存放在客户端,一般用来保存用户信息**。
下面是 `Cookie` 的一些应用案例:
1. 我们在 `Cookie` 中保存已经登录过的用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外,`Cookie` 还能保存用户首选项,主题和其他设置信息。
2. 使用 `Cookie` 保存 `Session` 或者 `Token` ,向后端发送请求的时候带上 `Cookie`,这样后端就能取到 `Session` 或者 `Token` 了。这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。
3. `Cookie` 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为 HTTP 协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在 `Cookie`
4. ......
## 如何在项目中使用 Cookie 呢?
我这里以 Spring Boot 项目为例。
**1)设置 `Cookie` 返回给客户端**
```java
@GetMapping("/change-username")
@ -64,7 +94,7 @@ public String readCookie(@CookieValue(value = "username", defaultValue = "Atta")
}
```
**3) 读取所有的 Cookie 值**
**3) 读取所有的 `Cookie` 值**
```java
@GetMapping("/all-cookies")
@ -80,64 +110,87 @@ public String readAllCookies(HttpServletRequest request) {
}
```
## 3. Cookie 和 Session 有什么区别如何使用Session进行身份验证
更多关于如何在 Spring Boot 中使用 `Cookie` 的内容可以查看这篇文章:[How to use cookies in Spring Boot](https://attacomsian.com/blog/cookies-spring-boot。) 。
**Session 的主要作用就是通过服务端记录用户的状态。** 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
## Cookie 和 Session 有什么区别?
**Cookie 数据保存在客户端(浏览器端)Session 数据保存在服务器端。相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。**
**`Session` 的主要作用就是通过服务端记录用户的状态。** 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 `Session` 之后就可以标识这个用户并且跟踪这个用户了。
**那么如何使用Session进行身份验证**
`Cookie` 数据保存在客户端(浏览器端)`Session` 数据保存在服务器端。相对来说 `Session` 安全性更高。如果使用 `Cookie` 的一些敏感信息不要写入 `Cookie` 中,最好能将 `Cookie` 信息加密然后使用到的时候再去服务器端解密。
很多时候我们都是通过 SessionID 来实现特定的用户SessionID 一般会选择存放在 Redis 中。举个例子:用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。关于这种认证方式更详细的过程如下:
**那么,如何使用 `Session` 进行身份验证?**
## 如何使用 Session-Cookie 方案进行身份验证?
很多时候我们都是通过 `SessionID` 来实现特定的用户,`SessionID` 一般会选择存放在 Redis 中。举个例子:
1. 用户成功登陆系统,然后返回给客户端具有 `SessionID``Cookie`
2. 当用户向后端发起请求的时候会把 `SessionID` 带上,这样后端就知道你的身份状态了。
关于这种认证方式更详细的过程如下:
![Session Based Authentication flow](./images/basis-of-authority-certification/Session-Based-Authentication-flow.png)
1. 用户向服务器发送用户名和密码用于登陆系统。
2. 服务器验证通过后,服务器为用户创建一个 Session并将 Session信息存储 起来。
3. 服务器向用户返回一个 SessionID写入用户的 Cookie。
4. 当用户保持登录状态时Cookie 将与每个后续请求一起被发送出去。
5. 服务器可以将存储在 Cookie 上的 Session ID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
2. 服务器验证通过后,服务器为用户创建一个 `Session`,并将 `Session` 信息存储 起来。
3. 服务器向用户返回一个 `SessionID`,写入用户的 `Cookie`
4. 当用户保持登录状态时,`Cookie` 将与每个后续请求一起被发送出去。
5. 服务器可以将存储在 `Cookie` 上的 `SessionID` 与存储在内存中或者数据库中的 `Session` 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
使用 Session 的时候需要注意下面几个点:
使用 `Session` 的时候需要注意下面几个点:
1. 依赖Session的关键业务一定要确保客户端开启了Cookie。
2. 注意Session的过期时间
1. 依赖 `Session` 的关键业务一定要确保客户端开启了 `Cookie`
2. 注意 `Session` 的过期时间
花了个图简单总结了一下Session认证涉及的一些东西。
画了个图简单总结了一下 `Session` 认证涉及的一些东西。
![](./images/basis-of-authority-certification/session-cookie-intro.jpeg)
![](./images/basis-of-authority-certification/Session-cookie-intro.jpeg)
另外Spring Session 提供了一种跨多个应用程序或实例管理用户会话信息的机制。如果想详细了解可以查看下面几篇很不错的文章:
- [Getting Started with Spring Session](https://codeboje.de/spring-session-tutorial/)
- [Guide to Spring Session](https://www.baeldung.com/spring-session)
- [Sticky Sessions with Spring Session & Redis](https://medium.com/@gvnix/sticky-sessions-with-spring-session-redis-bdc6f7438cc3)
- [Getting Started with Spring Session](https://codeboje.de/spring-Session-tutorial/)
- [Guide to Spring Session](https://www.baeldung.com/spring-Session)
- [Sticky Sessions with Spring Session & Redis](https://medium.com/@gvnix/sticky-Sessions-with-spring-Session-redis-bdc6f7438cc3)
## 4.如果没有Cookie的话Session还能用吗
## 多服务器节点下 Session-Cookie 方案如何做?
Session-Cookie 方案在单体环境是一个非常好的身份认证方案。但是当服务器水平拓展成多节点时Session-Cookie 方案就要面临挑战了。
举个例子:假如我们部署了两份相同的服务 AB用户第一次登陆的时候 Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。
**我们应该如何避免上面这种情况的出现呢?**
有几个方案可供大家参考:
1. 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
2. 每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
3. 单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点。
## 如果没有 Cookie 的话 Session 还能用吗?
这是一道经典的面试题!
一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID的方案的话 如果客户端禁用了Cookie那么Session就无法正常工作。
一般是通过 `Cookie` 来保存 `SessionID` ,假如你使用了 `Cookie` 保存 `SessionID` 的方案的话, 如果客户端禁用了 `Cookie`,那么 `Session` 就无法正常工作。
但是,并不是没有 Cookie 之后就不能用 Session 了比如你可以将SessionID放在请求的 url 里面`https://javaguide.cn/?session_id=xxx` 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 SessionID 进行一次加密之后再传入后端。
但是,并不是没有 `Cookie` 之后就不能用 `Session` 了,比如你可以将 `SessionID` 放在请求的 `url` 里面`https://javaguide.cn/?Session_id=xxx` 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 `SessionID` 进行一次加密之后再传入后端。
## 5.为什么Cookie 无法防止CSRF攻击而token可以
## 为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?
**CSRFCross Site Request Forgery**一般被翻译为 **跨站请求伪造** 。那么什么是 **跨站请求伪造** 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子:
小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了 10000 元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
```
```html
<a src=http://www.mybank.com/Transfer?bankId=11&money=10000>科学理财,年盈利率过万</>
```
上面也提到过,进行Session 认证的时候,我们一般使用 Cookie 来存储 SessionId,当我们登陆后后端生成一个SessionId放在Cookie中返回给客户端服务端通过Redis或者其他存储工具记录保存着这个Sessionid客户端登录以后每次请求都会带上这个SessionId服务端通过这个SessionId来标示你这个人。如果别人通过 cookie拿到了 SessionId 后就可以代替你的身份访问系统了。
上面也提到过,进行 `Session` 认证的时候,我们一般使用 `Cookie` 来存储 `SessionId`,当我们登陆后后端生成一个 `SessionId` 放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个 `SessionId`,客户端登录以后每次请求都会带上这个 `SessionId`,服务端通过这个 `SessionId` 来标示你这个人。如果别人通过 `Cookie` 拿到了 `SessionId` 后就可以代替你的身份访问系统了。
Session 认证中 Cookie 中的 SessionId是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
`Session` 认证中 `Cookie` 中的 `SessionId` 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
但是,我们使用 token 的话就不会存在这个问题,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。
但是,我们使用 `Token` 的话就不会存在这个问题,在我们登录成功获得 `Token` 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 `Token`,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 `Token` 的,所以这个请求将是非法的。
需要注意的是不论是 Cookie 还是 token 都无法避免跨站脚本攻击Cross Site ScriptingXSS
需要注意的是不论是 Cookie 还是 Token 都无法避免 **跨站脚本攻击Cross Site ScriptingXSS**
> 跨站脚本攻击Cross Site Scripting缩写为 CSS 但这会与层叠样式表Cascading Style SheetsCSS的缩写混淆。因此有人将跨站脚本攻击缩写为 XSS。
@ -145,7 +198,7 @@ XSS中攻击者会用各种方式将恶意代码注入到其他用户的页面
推荐阅读:[如何防止 CSRF 攻击?—美团技术团队](https://tech.meituan.com/2018/10/11/fe-security-csrf.html)
## 6. 什么是 Token?什么是 JWT?如何基于Token进行身份验证
## 什么是 Token?什么是 JWT?
我们在上一个问题中探讨了使用 Session 来鉴别用户的身份,并且给出了几个 Spring Session 的案例分享。 我们知道 Session 信息需要保存一份在服务器端。这种方式会带来一些麻烦,比如需要我们保证保存 Session 信息服务器的可用性、不适合移动端(依赖 Cookie等等。
@ -159,9 +212,11 @@ XSS中攻击者会用各种方式将恶意代码注入到其他用户的页面
JWT 由 3 部分构成:
1. Header :描述 JWT 的元数据。定义了生成签名的算法以及 Token 的类型。
2. Payload负载:用来存放实际需要传递的数据
3. Signature签名服务器通过`Payload``Header`和一个密钥(`secret`)使用 Header 里面指定的签名算法(默认是 HMAC SHA256生成。
1. **Header** : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
2. **Payload** : 用来存放实际需要传递的数据
3. **Signature签名** :服务器通过`Payload``Header`和一个密钥(`secret`)使用 Header 里面指定的签名算法(默认是 HMAC SHA256生成。
## 如何基于 Token 进行身份验证?
在基于 Token 进行身份验证的的应用程序中,服务器通过`Payload``Header`和一个密钥(`secret`)创建令牌(`Token`)并将 `Token` 发送给客户端,客户端将 `Token` 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization 字段中:`Authorization: Bearer Token`
@ -172,19 +227,18 @@ JWT 由 3 部分构成:
3. 用户以后每次向后端发请求都在 Header 中带上 JWT。
4. 服务端检查 JWT 并从中获取用户相关信息。
推荐阅读:
- [JWT (JSON Web Tokens) Are Better Than Session Cookies](https://dzone.com/articles/jwtjson-web-tokens-are-better-than-session-cookies)
- [JWT (JSON Web Tokens) Are Better Than Session Cookies](https://dzone.com/articles/jwtjson-web-Tokens-are-better-than-Session-cookies)
- [JSON Web Tokens (JWT) 与 Sessions](https://juejin.im/entry/577b7b56a3413100618c2938)
- [JSON Web Token 入门教程](https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html)
- [彻底理解CookieSessionToken](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485603&idx=1&sn=c8d324f44d6102e7b44554733da10bb7&chksm=cea24768f9d5ce7efe7291ddabce02b68db34073c7e7d9a7dc9a7f01c5a80cebe33ac75248df&token=844918801&lang=zh_CN#rd)
- [JSON Web Token 入门教程](https://www.ruanyifeng.com/blog/2018/07/json_web_Token-tutorial.html)
- [彻底理解 CookieSessionToken](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485603&idx=1&sn=c8d324f44d6102e7b44554733da10bb7&chksm=cea24768f9d5ce7efe7291ddabce02b68db34073c7e7d9a7dc9a7f01c5a80cebe33ac75248df&Token=844918801&lang=zh_CN#rd)
## 7 什么是OAuth 2.0
## 什么是 OAuth 2.0
OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。而 OAuth 2.0 是对 OAuth 1.0 的完全重新设计OAuth 2.0 更快更容易实现OAuth 1.0 已经被废弃。详情请见:[rfc6749](https://tools.ietf.org/html/rfc6749)。
实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 token使得第三方应用能够通过该令牌获取相关的资源。
实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 Token使得第三方应用能够通过该令牌获取相关的资源。
OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。
@ -201,16 +255,12 @@ OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了
- [OAuth 2.0 的四种方式](http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html)
- [GitHub OAuth 第三方登录示例教程](http://www.ruanyifeng.com/blog/2019/04/github-oauth.html)
## 8 什么是 SSO?
## 什么是 SSO?
SSO(Single Sign On)即单点登录说的是用户登陆多个子系统的其中一个就有权访问与其相关的其他系统。举个例子我们在登陆了京东金融之后,我们同时也成功登陆京东的京东超市、京东家电等子系统。
## 9.SSO与OAuth2.0的区别
OAuth 是一个行业的标准授权协议主要用来授权第三方应用获取有限的权限。SSO解决的是一个公司的多个相关的自系统的之间的登陆问题比如京东旗下相关子系统京东金融、京东超市、京东家电等等。
## 参考
- https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4
- https://medium.com/@sherryhsu/Session-vs-Token-based-authentication-11a6c5ac45e4
- https://www.varonis.com/blog/what-is-oauth/
- https://tools.ietf.org/html/rfc6749