diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index 038d687..3b8da08 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -5,7 +5,7 @@ import { backToTopPlugin } from '@vuepress/plugin-back-to-top' export default { lang: 'zh-CN', title: '拔土豆的程序员', - description: '不知道咋说,随便写写吧。', + description: '没进过大厂|技术一般|创业被坑|普普通通程序员', // markdown设置 markdown:{ lineNumbers: true, // 代码块行号 diff --git "a/docs/design/OAuth/OAuth2\345\222\214\345\215\225\347\202\271\347\231\273\345\275\225.md" "b/docs/design/OAuth/OAuth2\345\222\214\345\215\225\347\202\271\347\231\273\345\275\225.md" new file mode 100644 index 0000000..7babf2d --- /dev/null +++ "b/docs/design/OAuth/OAuth2\345\222\214\345\215\225\347\202\271\347\231\273\345\275\225.md" @@ -0,0 +1,5 @@ +# OAuth2和单点登录 + +OAuth2.0的应用场景可以理解为单点登录的升级版,单点登录解决了多个系统间会话的共享,OAuth2.0在此基础上增加了应用之间的权限控制 。 + +有些系统采用OAuth2.0模式实现了单点登录,但这总给人一种“杀鸡焉用宰牛刀”的感觉。 \ No newline at end of file diff --git "a/docs/design/OAuth/OAuth\345\237\272\346\234\254\346\246\202\345\277\265.md" "b/docs/design/OAuth/OAuth\345\237\272\346\234\254\346\246\202\345\277\265.md" new file mode 100644 index 0000000..a2650d9 --- /dev/null +++ "b/docs/design/OAuth/OAuth\345\237\272\346\234\254\346\246\202\345\277\265.md" @@ -0,0 +1,23 @@ +# OAuth 2.0 基本概念 + +OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方。 + +## OAuth2 授权流程中的角色 + +- 资源拥有者(`resource owner`) + - 最终用户:能授权访问受保护资源的一个实体,可以是一个人。 +- 资源服务器(`resource server`) + - 存储受保护资源,客户端通过`access token`请求资源,资源服务器响应受保护资源给客户端; +- 授权服务器(`authorization server`) + - 成功验证资源拥有者并获取授权之后,授权服务器颁发授权令牌(`Access Token`)给客户端。 +- 客户端(`client`) + - 第三方应用,也可以是它自己的官方应用;其本身不存储资源,而是资源拥有者授权通过后,使用它的授权(授权令牌)访问受保护资源,然后客户端把相应的数据展示出来/提交到服务器。 + +## 四种模式 + +1. 授权码(Authorization Code):OAuth2.0标准授权步骤,Server端向Client端下放Code码,Client端再用Code码换取授权Token +2. 隐藏式(Implicit):无法使用授权码模式时的备用选择,Server端使用URL重定向方式直接将Token下放到Client端页面 +3. 密码式(Password):Client直接拿着用户的账号密码换取授权Token +4. 客户端凭证(Client Credentials):Server端针对Client级别的Token,代表应用自身的资源授权 + +![https://oss.dev33.cn/sa-token/doc/oauth2/sa-oauth2-setup.png](image/sa-oauth2-setup.png) diff --git "a/docs/design/OAuth/OAuth\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/docs/design/OAuth/OAuth\345\270\270\350\247\201\351\227\256\351\242\230.md" new file mode 100644 index 0000000..3b117dc --- /dev/null +++ "b/docs/design/OAuth/OAuth\345\270\270\350\247\201\351\227\256\351\242\230.md" @@ -0,0 +1,67 @@ +# OAuth常见问题 + +## 前后端分离:登录页面和授权确认页面 + +问题: + +1. OAuth 2 授权的时候会302重定向到授权服务器提供的登录页面和授权确认页面。 + +原因: + +1. OAuth2客户端和授权服务器之间并不是一个完全信任的关系。 + +例如现在智能门锁已经很普及了,一般都会有临时密码,而不是告诉访客实际密码。 + +ajax无法安全地处理OAuth2授权流程中的302重定向问题,这也是一个技术问题。 + +## 常用场景 + +OAuth2主要用于API授权,是跨API服务之间授权的解决方案。 + +1. 单点登录(SSO) +2. 微服务之间的授权鉴权 +3. API开放平台等场景。 + +## 密码模式为什么被废除 + +OAuth2.1中密码模式被移除,包括OAuth0、okta等知名三方授权服务机构都对密码模式进行了移除处理。 + +密码模式诞生的时候,像React、Vue这种单页应用还没有兴起,甚至连框架都还没有呢。它更像一种为了解决遗留问题而采用的过渡方案。在传统应用中,用户习惯了把密码直接交给客户端换取资源访问权限,而不是跳来跳去去拉授权、确认授权。OAuth2诞生之初为了让用户从传统思维中慢慢转变过来就设计了这种模式。 它打破了委托授权的模式,降低了OAuth2的安全性。 + +## 微服务是否可以不使用OAuth2 + +可以,OAuth2只不过是目前微服务访问控制的解决方案之一,并不是唯一选项。 + +## 资源服务器 + +只要包含了需要OAuth2客户端携带access_token访问的资源接口的服务器都可以认为是资源服务器,包括OAuth2客户端、OAuth2授权服务器都可以根据业务和架构承担资源服务器的功能。从用户(资源所有者)角度来说,存放用户可以授权的资源接口的服务器都可以是资源服务器。资源服务器可以对访问令牌access_token进行解码、校验,并确定本次请求是否合规。 + +## 客户端认证是什么 + +confidential类型的OAuth2客户端虽然在OAuth2授权服务器注册,它们要根据一些策略(Client Authentication Method)来向授权服务器证明自己是合法的客户端。这样它们才能调用一些OAuth2规定的端点,比如/oauth2/token令牌端点、/oauth2/revoke令牌撤销端点等等。关于OAuth2客户端认证的细节可以参考OAuth2客户端认证过滤器详解。 + +## 客户端能否做用户认证 + +OAuth2本身并没有定义用户如何向OAuth2客户端认证身份,这里要和授权服务器上的用户认证区别开来。OAuth2客户端在完成授权时可以拿到授权凭据,但是并不能直接拿到用户信息,如果授权服务器提供了获取用户信息的资源接口,OAuth2客户端可以通过该接口尝试获取用户信息用来表明用户的身份,这取决于用户是否授权了OAuth2客户端这样做。OIDC 1.0补充定义了OAuth2客户端对用户进行认证的细节流程。 + +## scope是什么 + +OAuth2是一个授权框架,授权自然要划定一个范围(scope),以保证OAuth2客户端在既定的范围内行事而不越界。它起到的作用和RBAC中的role其实类似,都是用来限制资源的访问权限的。role针对的是资源拥有者(Resource Owner),而scope针对的是OAuth2客户端。当然有一个例外openid,这个是OIDC 1.0的标识,算一个关键字。 + +## access_token和refresh_token应该直接返回给前端吗 + +能不能返回给前端取决于这个前端是不是直接在授权服务器的OAuth2客户端,如果不是,就不能持有access_token和refresh_token,access_token和refresh_token的签发目标只能是OAuth2客户端。如果暴露面放开,则很容易被盗用。 + +## 非OAuth2客户端的客户端应用既然不能直接持有access_token和refresh_token的话,应该如何获取授权状态 + +当授权成功后,令牌和用户客户端侧可以借助于session或者cookie进行一个映射,当然也可以考虑计算出一个不透明令牌( Opaque Token )映射,具体根据业务考量。 + +## 客户端为什么分为public和confidential两种类型,分别是什么场景 + +相关定义参见rfc6749#section-2.1, 根据OAuth2客户端自身是否有能力维护客户端凭据(client credentials)的私密性,是否能安全地通过授权服务器对客户端的资质进行认证将OAuth2客户端分为机密客户端和公共客户端。大部分的后端数据服务都应该被注册为机密客户端;无法保障自身凭据安全的都应该被注册为公共客户端,公共客户端是没有client_sercet的,直接注册到OAuth2授权服务器的执行客户端,不通过后端应用进行访问令牌中继的都是公共客户端,特定场景需要直连授权服务器的Web应用、移动应用都属于这一类。 + +## 什么是OAuth2客户端 + +在OAuth2授权服务器上注册为客户端,并获得专属client_id标识的才是OAuth2客户端。 + +安卓应用、IOS应用、Web前端等客户端应用也要遵循这个原则,它们本身注册到OAuth2授权服务器才能成为OAuth2客户端,否则就不是OAuth2客户端,必须是它们本身,而不是支撑它们的后端服务。 diff --git a/docs/design/OAuth/README.md b/docs/design/OAuth/README.md index e49b284..5b404e2 100644 --- a/docs/design/OAuth/README.md +++ b/docs/design/OAuth/README.md @@ -1,2 +1,7 @@ # OAuth +[OAuth基本概念](./OAuth基本概念.md) + +[OAuth2和单点登录](./OAuth2和单点登录.md) + +[OAuth常见问题](./OAuth常见问题.md) diff --git a/docs/design/OAuth/image/sa-oauth2-setup.png b/docs/design/OAuth/image/sa-oauth2-setup.png new file mode 100644 index 0000000..f7016d0 Binary files /dev/null and b/docs/design/OAuth/image/sa-oauth2-setup.png differ diff --git a/docs/design/distributed/README.md b/docs/design/distributed/README.md index 4708cab..4bc52f4 100644 --- a/docs/design/distributed/README.md +++ b/docs/design/distributed/README.md @@ -4,6 +4,8 @@ [高并发性能指标](./高并发性能指标.md) +[微服务中台等等设计](./微服务中台等等设计.md) + ## 分库分表 [分库分表策略以及平滑扩容](./分库分表策略以及平滑扩容.md) diff --git "a/docs/design/distributed/\345\276\256\346\234\215\345\212\241\344\270\255\345\217\260\347\255\211\347\255\211\350\256\276\350\256\241.md" "b/docs/design/distributed/\345\276\256\346\234\215\345\212\241\344\270\255\345\217\260\347\255\211\347\255\211\350\256\276\350\256\241.md" new file mode 100644 index 0000000..ea3bc79 --- /dev/null +++ "b/docs/design/distributed/\345\276\256\346\234\215\345\212\241\344\270\255\345\217\260\347\255\211\347\255\211\350\256\276\350\256\241.md" @@ -0,0 +1,21 @@ +# 微服务和中台 + +- 微服务架构的核心理念是将一个应用拆分成小而自治的服务。 + +- 中台则在企业内部构建共享的技术平台,以提高效率和协同。 + +虽然微服务具有灵活性和独立性的优点,但同时也增加了系统复杂性、调试、管理、交付成本。这些挑战需要通过引入微服务治理来解决,治理本身带来一定的成本。 + +中台的构建需要企业进行组织和文化上的变革,这不是一蹴而就的过程。 + + + +新的理念虽然能够解决当前问题,但并非银弹,根据历史经验,新的理念和技术总会带来新的挑战,比如微服务治理。微服务治理不仅仅包括服务注册、发现、配置中心,还包括DevOps、CI、CD等方面。 + +在面对一些新的理念货概念(包括微服务、中台),研发人员往往会陷入0/1游戏,对、错的思考模式。然而,更合理的方式是首先了解当前项目或产品所面临的困境和场景,考虑技术引入可能带来的成本和价值,而不是盲目跟从他人观点。 + +成功的商业公司如Netflix、亚马逊等证明了微服务的有效性,但商业战略上的失败通常涉及多个因素。将责任归咎于微服务或中台显然是一种失偏颇的观点。 + +这就像产品不成功,把失败的原因归咎于研发人员不给力一样滑稽。 + +> 摘自:Ahoo-Wang \ No newline at end of file diff --git a/docs/spring/spring/README.md b/docs/spring/spring/README.md index 0b5cd3d..832fd8e 100644 --- a/docs/spring/spring/README.md +++ b/docs/spring/spring/README.md @@ -16,3 +16,6 @@ [Spring中事务以及事务的传播机制](./Spring中事务以及事务的传播机制.md) +1、nginx 摘流 +2、等 http、rpc、mq、job 执行完,或者搓一点 sleep 60-120 秒 +3、shutdown diff --git "a/docs/spring/springBoot/OAuth2Client\345\257\271\346\216\245\350\256\244\350\257\201\346\234\215\345\212\241.md" "b/docs/spring/springBoot/OAuth2Client\345\257\271\346\216\245\350\256\244\350\257\201\346\234\215\345\212\241.md" new file mode 100644 index 0000000..c821dbb --- /dev/null +++ "b/docs/spring/springBoot/OAuth2Client\345\257\271\346\216\245\350\256\244\350\257\201\346\234\215\345\212\241.md" @@ -0,0 +1,30 @@ +# OAuth2 Client对接认证服务 + +项目在初始化时会根据配置的issuer-uri拼接url,即签发地址根目录/.well-known/openid-configuration,像项目中配置的就是该接口会返回认证服务器的元信息。 + +```web-idl +http://127.0.0.1:9000/.well-known/openid-configuration +``` + +![image-20231220150034474](image/image-20231220150034474.png) + +## cookie 问题 + +认证服务器和客户端在同一个机器上时不能使用同一个ip。[Not able to connect Spring OAuth2 Authorization Server with Client · Issue #5946 · spring-projects/spring-security (github.com)](https://github.com/spring-projects/spring-security/issues/5946) + +可以一个使用 192.168.18.14:9001(内网)一个使用 127.0.0.1 + +## 客户端 + +客户端在oauth2角色解释中是第三方的一个应用,一般会配合资源服务一起使用。 + +单体项目 + +- 会同时添加资源服务依赖,客户端负责调用认证服务登录,资源服务器负责解析获取到的token,然后获取token中的权限,目前token中的权限只有scope的权限,并且不太好自定义,所以就需要通过资源服务器配置去更好的解析token。 + + + +分布式项目: + +- 在网关中添加客户端依赖,检查用户认证信息,由网关代理的微服务添加资源服务依赖,解析网关通过令牌中继的方式携带的access_token;各个微服务添加自己的授权校验。 +- 在网关中集成客户端依赖,同时集成资源服务依赖,由网关检查用户的认证和授权信息;各个微服务不用添加任何的认证与授权相关的处理,可以直接访问;这种方式需要屏蔽各微服务其它ip的访问,只能由网关代理访问。 diff --git a/docs/spring/springBoot/README.md b/docs/spring/springBoot/README.md index 17b116e..b44677f 100644 --- a/docs/spring/springBoot/README.md +++ b/docs/spring/springBoot/README.md @@ -2,6 +2,32 @@ 梳理 Spring Boot 相关内容。 +## spring-authorization-server + +示例项目:[lizhifuabc/spring-authorization-server-example: Spring OAuth2 Authorization Server 集成,认证服务、第三方登录、自定义grant_type等等 (github.com)](https://github.com/lizhifuabc/spring-authorization-server-example) + + + +[01基本概念](./基本概念.md) + +[SpringAuthorizationServer-02](./SpringAuthorizationServer-02.md) + +[03自定义异常响应配置](./SpringAuthorizationServer-03.md) + +[04常用端点](./常用端点.md) + +[客户端认证授权.md](./客户端认证授权.md) + +[资源服务器](./资源服务器.md) + +[SpringAuthorizationServer-07](./SpringAuthorizationServer-07.md) + +[SpringAuthorizationServer-08](./SpringAuthorizationServer-08.md) + +[SpringAuthorizationServer-09](./SpringAuthorizationServer-09.md) + +[SpringAuthorizationServer-10](./SpringAuthorizationServer-10.md) + ## 项目地址 [lizhifuabc/spring-learn: springboot3、springcloud、java基础 (github.com)](https://github.com/lizhifuabc/spring-learn) diff --git a/docs/spring/springBoot/SpringAuthorizationServer-02.md b/docs/spring/springBoot/SpringAuthorizationServer-02.md new file mode 100644 index 0000000..74d0149 --- /dev/null +++ b/docs/spring/springBoot/SpringAuthorizationServer-02.md @@ -0,0 +1,9 @@ +# SpringAuthorizationServer-02 + + + +## 自定义用户登录页 + +## 自定义用户确认授权页 + +## 自定义RegisteredClientRepository \ No newline at end of file diff --git a/docs/spring/springBoot/SpringAuthorizationServer-03.md b/docs/spring/springBoot/SpringAuthorizationServer-03.md new file mode 100644 index 0000000..da5c45c --- /dev/null +++ b/docs/spring/springBoot/SpringAuthorizationServer-03.md @@ -0,0 +1,11 @@ +# 自定义异常响应配置 + +Spring Security中的异常主要分为两大类 + +- 认证异常(`AuthenticationException`),这个是所有认证异常的父类 +- 权限异常(`AccessDeniedException`),这个是所有权限异常的父类 + + + +按照oauth协议,异常信息放在响应头中,响应头的key是**WWW-Authenticate**。 + diff --git a/docs/spring/springBoot/image/image-20231218160556003.png b/docs/spring/springBoot/image/image-20231218160556003.png new file mode 100644 index 0000000..0c3cea9 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231218160556003.png differ diff --git a/docs/spring/springBoot/image/image-20231219144958834.png b/docs/spring/springBoot/image/image-20231219144958834.png new file mode 100644 index 0000000..18ca0e3 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231219144958834.png differ diff --git a/docs/spring/springBoot/image/image-20231219161618501.png b/docs/spring/springBoot/image/image-20231219161618501.png new file mode 100644 index 0000000..4c9e781 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231219161618501.png differ diff --git a/docs/spring/springBoot/image/image-20231219162021948.png b/docs/spring/springBoot/image/image-20231219162021948.png new file mode 100644 index 0000000..e7bbcb1 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231219162021948.png differ diff --git a/docs/spring/springBoot/image/image-20231219163456855.png b/docs/spring/springBoot/image/image-20231219163456855.png new file mode 100644 index 0000000..6a46ef9 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231219163456855.png differ diff --git a/docs/spring/springBoot/image/image-20231220150034474.png b/docs/spring/springBoot/image/image-20231220150034474.png new file mode 100644 index 0000000..1647ab9 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231220150034474.png differ diff --git a/docs/spring/springBoot/image/image-20231225111639272.png b/docs/spring/springBoot/image/image-20231225111639272.png new file mode 100644 index 0000000..34c2565 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231225111639272.png differ diff --git a/docs/spring/springBoot/image/image-20231225111714816.png b/docs/spring/springBoot/image/image-20231225111714816.png new file mode 100644 index 0000000..34c2565 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231225111714816.png differ diff --git a/docs/spring/springBoot/image/image-20231225122432983.png b/docs/spring/springBoot/image/image-20231225122432983.png new file mode 100644 index 0000000..1145192 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231225122432983.png differ diff --git a/docs/spring/springBoot/image/image-20231226123059081.png b/docs/spring/springBoot/image/image-20231226123059081.png new file mode 100644 index 0000000..3d57d2d Binary files /dev/null and b/docs/spring/springBoot/image/image-20231226123059081.png differ diff --git a/docs/spring/springBoot/image/image-20231226123130978.png b/docs/spring/springBoot/image/image-20231226123130978.png new file mode 100644 index 0000000..082efb4 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231226123130978.png differ diff --git a/docs/spring/springBoot/image/image-20231226123517209.png b/docs/spring/springBoot/image/image-20231226123517209.png new file mode 100644 index 0000000..59217c5 Binary files /dev/null and b/docs/spring/springBoot/image/image-20231226123517209.png differ diff --git "a/docs/spring/springBoot/\345\237\272\346\234\254\346\246\202\345\277\265.md" "b/docs/spring/springBoot/\345\237\272\346\234\254\346\246\202\345\277\265.md" new file mode 100644 index 0000000..507071b --- /dev/null +++ "b/docs/spring/springBoot/\345\237\272\346\234\254\346\246\202\345\277\265.md" @@ -0,0 +1,103 @@ +# SpringAuthorizationServer-基本概念 + +OAuth2是一个对外开放的第三方授权协议,允许用户不提供第三方应用的账号信息的前提下以授权的方式获得第三方应用资源的访问令牌,从而能够访问第三方资源。 + +## Spring Authorization Server + + + +## 认证与授权 + +认证(Authentication):用户认证,就是验证此用户的身份。解决的是‘我是谁’的问题。就是从用户请求信息中获取用户信息的过程,认证是一个过程。 + +> 当你在登录时,输入用户名密码,系统判断你的用户名与密码是否在已有的用户内并给出结果反馈,这个过程就是用户认证。 +> 用户名+密码登录,手机、邮箱验证码,第三方登录等都属于用户认证的一种。 + +授权(Authorization):用户授权,就是授予用户权限,能够进行后续的某些访问和操作。解决的是“我能干那些事”的问题。就是从获取到用户信息到授予用户权限的过程。 + +> 每天乘电梯刷卡,刷卡的过程就是授权,授予了我们访问某某层的权限。就相当于是某个人或者某个机构赋予某人干某事的权限的过程。 + +## 认证角色[draft-ietf-oauth-v2-1-07](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#name-roles) + +1. Resource Owner:资源拥有者;能够授予对受保护资源的访问权限的实体,通常指的是终端用户。 + +2. Client:客户端;代表资源所有者发出受保护资源请求并获得其授权的应用程序。 + +3. Authorization Server:认证服务器;服务器在成功对资源所有者进行身份验证并获得授权后向客户端发出访问令牌。 + +4. Resource Server:资源服务器;托管受保护资源的服务器,能够使用访问令牌接受和响应受保护的资源请求。 + +## 授权模式 + +oauth2.1移除了隐式授权模式(Implicit grant)和密码模式(Resource Owner Password Credentials Grant)。 + +oauth2.0区别:[draft-ietf-oauth-v2-1-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-00#name-differences-from-oauth-20) + +传统的用户名和密码登录方式会出现安全问题,相当于你在不受信任的网站登录时候,使用了受信任的网站的信息。但Oauth2更偏向于授权,实际上如果你不勾选授权,他是无法访问到你的个人信息(头像那些),这也是为什么很多时候授权勾选个人信息的框是灰色,默认选中的原因。密码模式移除:[draft-ietf-oauth-security-topics-24](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#name-resource-owner-password-cre) + + + +**授权模式** + +- 授权码模式:[draft-ietf-oauth-v2-1-07](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#name-authorization-code-grant) + + 授权码模式(Authorization Code Grant)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动; + +- 授权码扩展流程PKCE:[RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (ietf.org)](https://datatracker.ietf.org/doc/html/rfc7636) + + 使用授权码授予的OAuth 2.0公共客户端是易受授权码拦截攻击。该流程可以减轻攻击,通过使用代码交换证明密钥来抵御威胁。客户端生成code_verifier和code_challenge跟认证服务器进行交互,以生成的随机认证码进行身份认证。 + +- 客户端模式:[draft-ietf-oauth-v2-1-07](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#name-client-credentials-grant) + + 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题; + + +- 设备授权码模式:[RFC 8628 - OAuth 2.0 Device Authorization Grant (ietf.org)](https://datatracker.ietf.org/doc/html/rfc8628) + + 设备授权码模式(Device Authorization Grant)主要会出现在凭证式授权类型中,为设备代码,设备流中无浏览器或输入受限的设备提供的一种认证方式,设备会让用户在另一台设备上的浏览器中访问一个网页,以进行登录。 用户登录后,设备可以获取所需的访问令牌和刷新令牌; + + 刷新access token:刷新令牌在获取access token时会同步获取刷新令牌(Refresh token),如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌(Refresh token)"申请一个新的访问令牌。 + +## Token + +令牌生成器:框架提供了令牌生成器(OAuth2TokenGenerator),负责从提供的OAuth2TokenContext中根据TokenType类型生成对应的OAuth2Token,tokenGenerator很灵活,它可以支持access_token和refresh_token的任何自定义令牌格式。 + + +JWT [RFC 7519 - JSON Web Token (JWT) (ietf.org)](https://datatracker.ietf.org/doc/html/rfc7519) + + +JWS [RFC 7515 - JSON Web Signature (JWS) (ietf.org)](https://datatracker.ietf.org/doc/html/rfc7515) + +## 客户端认证方式 + +### client_secret_basic + +客户端将clientId 和 clientSecret 通过 ‘:’ 号拼接,并使用 Base64 进行编码得到一个字符串。将此编码字符串放到请求头(Authorization)去发送请求。授权服务器通过获取请求头中的clientId和clientSecret对客户端进行认证。 + +### client_secret_post + +客户端将 clientId 和 clientSecret 放到请求体(表单)去发送请求。授权服务器获取请求参数中的clientId和clientSecret对客户端进行认证。 + +### client_secret_jwt + +client_secret_jwt方式就是利用 JWT 进行认证。请求方和授权服务器,两者都知道客户端的 client_secret,通过相同的 HMAC 算法(对称签名算法)去加签和验签 JWT ,可以达到客户端认证的目的。请求方通过HMAC算法,以 client_secret 作为密钥,将客户端信息加签生成 JWT;授权服务器使用相同的HMAC算法和client_secret,对请求方的 JWT 进行验签以认证客户端。 + +### private_key_jwt + +private_key_jwt 方式就是利用 JWT 进行认证;请求方拥有自己的公私钥(密钥对),使用私钥对 JWT 加签,并将公钥暴露给授权服务器;授权服务器通过请求方的公钥验证 JWT,也能达到客户端认证的目的。请求方维护了一对公私钥,通过 RSA算法,使用私钥将客户端信息加签生成 JWT;另外还通过接口暴露公钥给授权服务器;授权服务器使用请求方的公钥对请求方的 JWT进行验签以认证客户端。 + +### none (public clients) + +当客户端是公共客户端时认证服务器不会对客户端进行验证,PKCE(Proof Key for Code Exchange)流程要求客户端为公共客户端。 + +## 认证服务器端点 + +[Protocol Endpoints :: Spring Authorization Server](https://docs.spring.io/spring-authorization-server/reference/protocol-endpoints.html) + +包含OAuth2.1和Open Connect 1.0相关端点。 + + + +> https://blog.csdn.net/qq_44005305/article/details/129029653 +> +> https://juejin.cn/post/7239953874950733884 \ No newline at end of file diff --git "a/docs/spring/springBoot/\345\256\242\346\210\267\347\253\257\350\256\244\350\257\201\346\216\210\346\235\203.md" "b/docs/spring/springBoot/\345\256\242\346\210\267\347\253\257\350\256\244\350\257\201\346\216\210\346\235\203.md" new file mode 100644 index 0000000..04276c7 --- /dev/null +++ "b/docs/spring/springBoot/\345\256\242\346\210\267\347\253\257\350\256\244\350\257\201\346\216\210\346\235\203.md" @@ -0,0 +1,36 @@ +# 客户端认证授权 + +[lizhifuabc/spring-authorization-server-example: Spring OAuth2 Authorization Server 集成,认证服务、第三方登录、自定义grant_type等等 (github.com)](https://github.com/lizhifuabc/spring-authorization-server-example) + +客户端在oauth2角色解释中是第三方的一个应用,一般会配合资源服务一起使用。即客户端也是资源服务器。 + +1. 单体项目 + 1. 同时添加资源服务依赖,客户端负责调用认证服务登录 + 2. 资源服务器配置解析token +2. 网关项目 + 1. 网关中添加客户端依赖,检查用户认证信息,由网关代理的微服务添加资源服务依赖,解析网关通过令牌中继的方式携带的access_token;各个微服务添加自己的授权校验。 + 2. 网关中集成客户端依赖,同时集成资源服务依赖,由网关检查用户的认证和授权信息;各个微服务不用添加任何的认证与授权相关的处理,可以直接访问;这种方式需要屏蔽各微服务其它ip的访问,只能由网关代理访问。 + +## 访问受限资源:@PreAuthorize + +http://auth-client:9001/read + +http://auth-client:9001/write + +![image-20231225122432983](image/image-20231225122432983.png) + +1. 访问受限资源:@PreAuthorize +2. 没有登录信息重定向至认证服务器去请求授权 +3. return:没有登录则重定向至登录页面 + +## 用户使用账号密码登录 + +![image-20231226123130978](image/image-20231226123130978.png) + +![image-20231226123059081](image/image-20231226123059081.png) + +## 端点 + +> http://auth-server:9000/.well-known/openid-configuration + +![image-20231226123517209](image/image-20231226123517209.png) diff --git "a/docs/spring/springBoot/\345\270\270\347\224\250\347\253\257\347\202\271.md" "b/docs/spring/springBoot/\345\270\270\347\224\250\347\253\257\347\202\271.md" new file mode 100644 index 0000000..2f83779 --- /dev/null +++ "b/docs/spring/springBoot/\345\270\270\347\224\250\347\253\257\347\202\271.md" @@ -0,0 +1,89 @@ +# 常用端点 + +- **OAuth2 Authorization Endpoint**:申请授权端点,默认为`/oauth2/authorize` +- **OAuth2 Token Endpoint**:获取访问令牌端点,默认为`/oauth2/token` +- **OAuth2 Token Introspection Endpoint**:令牌自省端点,默认为`/oauth2/introspect` +- **OAuth2 Token Revocation Endpoint**:令牌撤销端点,默认为`/oauth2/revoke` +- **OAuth2 Authorization Server Metadata Endpoint**:获取授权服务器元信息的端点,默认为`/.well-known/oauth-authorization-server` +- **JWK Set Endpoint**:`JWK`信息端点,默认为`/oauth2/jwks` +- **OpenID Connect 1.0 Provider Configuration Endpoint**:查询提供者配置端点,默认为`/.well-known/openid-configuration` +- **OpenID Connect 1.0 UserInfo Endpoint**:用户信息端点,默认为`/userinfo` +- **OpenID Connect 1.0 Client Registration Endpoint**:客户端注册端点,默认为`/connect/registe` + + + +## 测试 + + +/oauth2/token:OAuth 2.0 的令牌端点,用于交换授权码或刷新令牌,获取访问令牌或 ID 令牌。 + +/oauth2/jwks:JWK 集合端点,用于提供用于 JWT 签名和验证的公钥。 + +```java +// 获取授权服务器 AccessToken 解码公钥 +http://127.0.0.1:9000/oauth2/jwks +``` + +![image-20231219144958834](image/image-20231219144958834.png) + +/oauth2/userinfo:用户信息端点,用于获取已授权用户的个人资料信息。 +/oauth2/keys:JSON Web Key Set 端点,用于提供签名密钥和加密密钥。 + +```java +http://127.0.0.1:9000/oauth2/keys +``` + +/oauth2/.well-known/jwks-uri:OpenID Connect 端点,用于公开 JWK 集合的 URL。 + +```java +http://127.0.0.1:9000/.well-known/jwks-uri +``` + +```json +{"issuer":"http://127.0.0.1:9000","authorization_endpoint":"http://127.0.0.1:9000/oauth2/authorize","device_authorization_endpoint":"http://127.0.0.1:9000/oauth2/device_authorization","token_endpoint":"http://127.0.0.1:9000/oauth2/token","token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt"],"jwks_uri":"http://127.0.0.1:9000/oauth2/jwks","response_types_supported":["code"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","urn:ietf:params:oauth:grant-type:device_code"],"revocation_endpoint":"http://127.0.0.1:9000/oauth2/revoke","revocation_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt"],"introspection_endpoint":"http://127.0.0.1:9000/oauth2/introspect","introspection_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt"],"code_challenge_methods_supported":["S256"]} +``` + + + +1. /oauth2/authorize OAuth 2.0 的授权端点,用于获取授权码或访问令牌。: +response_type:必需。表示授权服务器应该返回的授权类型。通常为 code 或 token。 +client_id:必需。客户端 ID,授权服务器用于验证客户端。 +redirect_uri:可选。授权服务器重定向用户的 URI。 +scope:可选。表示客户端请求的授权范围。 +state:可选。授权服务器将在重定向 URI 中包含此参数,用于防止 CSRF 攻击。 +code_challenge 和 code_challenge_method:可选。用于 PKCE 验证的参数。 + +```java +// 重定向至登录页面 +http://127.0.0.1:9000/oauth2/authorize?client_id=messaging-client&response_type=code&scope=message.read&redirect_uri=https://www.baidu.com +``` + +![image-20231219161618501](image/image-20231219161618501.png) + + + +```java +https://www.baidu.com/?code=4kQNAfKd9615R_7FbqmMUhz4P8oPI76gP9Jngx4HstYqyHbmHpzab8JtXnhE70OWZgBfVUvmfjXcLNRBbi7BIWsV9vNFHMn5V6EkoAJFGCm4MJzByvjjiZQa7_eP_3ww +``` + + + +2. /oauth2/token 根据code换取AccessToken,令牌端点的请求参数: + grant_type:必需。表示客户端请求的授权类型,通常为 authorization_code、password、client_credentials 或 refresh_token。 + code:必需(仅在授权类型为 authorization_code 时)。授权码。 + redirect_uri:必需(仅在授权类型为 authorization_code 时)。与请求授权码时使用的重定向 URI 相同。 + client_id 和 client_secret:必需。客户端 ID 和密钥。 + username 和 password:必需(仅在授权类型为 password 时)。用户凭据。 + refresh_token:必需(仅在授权类型为 refresh_token 时)。刷新令牌。 + scope:可选。请求的授权范围。 + +![image-20231219162021948](image/image-20231219162021948.png) + +![image-20231219163456855](image/image-20231219163456855.png) + +/oauth2/userinfo 用户信息端点的请求参数: +access_token:必需。访问令牌。 + +/oauth2/keys JSON Web Key Set 端点的请求参数:无。 + +/oauth2/.well-known/jwks-uri OpenID Connect 端点的请求参数:无。 diff --git "a/docs/spring/springBoot/\350\265\204\346\272\220\346\234\215\345\212\241\345\231\250.md" "b/docs/spring/springBoot/\350\265\204\346\272\220\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..be263dd --- /dev/null +++ "b/docs/spring/springBoot/\350\265\204\346\272\220\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,26 @@ +# 资源服务器 + +[OAuth 2.0 Resource Server :: Spring Security](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/index.html) + +注意: + +Resource server和oauth2 client一样,是一个单独的服务,不需要跟认证服务器的版本保持一致。 + +## Bearer Tokens + +[OAuth 2.0 Bearer Tokens :: Spring Security](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/bearer-tokens.html) + +默认情况下,资源服务器在Authorization标头中查找承载令牌。 + +## 示例 + +[lizhifuabc/spring-authorization-server-example: Spring OAuth2 Authorization Server 集成,认证服务、第三方登录、自定义grant_type等等 (github.com)](https://github.com/lizhifuabc/spring-authorization-server-example) + +### 访问未授权地址 + +http://127.0.0.1:9002/demo01 + +![image-20231225111714816](image/image-20231225111714816.png) + +### 认证服务器获取 access_token + diff --git a/docs/started/README.md b/docs/started/README.md index db7b8f0..6551fb9 100644 --- a/docs/started/README.md +++ b/docs/started/README.md @@ -4,6 +4,10 @@ 随着事件的推移,对于很多事的理解也在变化。 + + +[保命check list](./checkList.md) + ## 阅读源码 [2023年10月25日阅读源码没有意义](./2023年10月25日阅读源码没有意义.md) \ No newline at end of file diff --git a/docs/started/checkList.md b/docs/started/checkList.md new file mode 100644 index 0000000..abcfd19 --- /dev/null +++ b/docs/started/checkList.md @@ -0,0 +1,63 @@ +# 保命 + +总结自己在做后端开发的 check list ,目的是保命,依次是:**需求分析->功能设计->编码阶段->测试阶段->上线阶段->检视阶段。** + +## 1. 需求分析 + +1. 当需求本身存在不明确的地方时,是否有和产品进行沟通? +2. 基于需求想要解决的问题,是否有从研发角度找出是否有更优的实现方案? +3. 需求拆分和工时估算中,是否拆分的足够细? +4. 需求拆分和工时估算中,是否考虑到自测时间? +5. 需求拆分和工时估算中,是否考虑到联调时间? +6. 需求拆分和工时估算中,是否考虑到留出一定冗余时间? + +## 2. 功能设计 + +1. 需求本身复杂度较高时,是否有考虑先画流程图? +2. 需求本身或者开发过程中,是否有可能涉及安全问题? +3. 需求本身是否设计到状态流转,是否有考虑先画流程图? +4. 是否有涉及好判定功能正常与否的关键指标? +5. 是否涉及删除功能,删除是否有使用校验? +6. 功能设计给大家 review 之前,是否有自己对着需求文档过一遍逻辑和格式? +7. 数据库:普通索引是否创建? +8. 数据库:唯一性索引是否创建,是否牵扯到删除的问题? +9. 多租户 + 1. 是否有数据安全性问题? + +## 3. 编码阶段 + +1. 是否有将数据库变更同步到测试环境? +2. 是否存在漏打日志,异常处理是否规范? +3. 是否存在并发问题,事务是否能够保证一致性? +4. 是否存在远程调用,远程调用失败是否有后续操作(日志或者重试机制)? +5. 是否有对核心逻辑,复杂逻辑进行单元测试覆盖? +6. 是否有合理的日志覆盖用于上线后的正常与否判定,以及问题追踪? +7. 是否修改了现有代码,如果修改是否通知相关调用方? +8. 提交 PR 之前,是否有自己先过一遍代码规范? +9. 提交 PR 之前,是否有在本地跑过单元测试? + +## 4. 测试阶段 + +这里举例常见的一个增删改查的需求。备注:这里是 check 测试用例以及执行测试用例,而测试用例的构建,我建议放在编码阶段之前。 + +1. 对于输入参数是否进行了有效性校验? +2. 对于输入参数是否进行了边界值校验? +3. 对于权限校验是否有进行确认? +4. 对于返回参数的格式和数据是否进行确认? + +## 5. 上线阶段 + +1. 是否有确认过各个项目的部署顺序依赖? +2. 是否有和其他同事确认过此时可以上线? +3. 是否有线上配置文件更改,例如nacos? +4. 是否有数据库上线? + 1. 新建字段,有没有默认值? + 2. 修改字段,原有数据怎么处理? + 3. 修改字段默认值,原有数据是否更改? + 4. 是否需要备份更改的数据? + 5. 是否存在锁库的问题? + + +## 6. 检视阶段 + +1. 是否有按照功能设计阶段制定的计划,对关键的数据指标或者日志进行检查? \ No newline at end of file