天天看点

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

微服务 Spring Security OAuth2.0认证授权

  • 1. 基本概念
    • 1.1 什么是认证
    • 1.2 什么是会话
    • 1.3 什么是授权
    • 1.4 授权数据模型
      • 1.4.1 授权认证流程
      • 1.4.2 ER关系模型
    • 1.5 RBAC
  • 2. 基于session的认证方式
    • 2.1 基于session认证流程
    • 2.2 基于session总结
  • 3. spring security原理分析
    • 3.1 结构总览
    • 3.2 认证流程
      • 3.2.1 认证流程
      • 3.2.2 AuthenticationProvider
      • 3.2.3 UserDetailsService
      • 3.2.4 PasswordEncoder
    • 3.3 授权流程
      • 3.3.1 授权流程
      • 3.3.1 授权决策
  • 4.分布式系统认证方案
    • 4.1分布式架构
    • 4.2 分布式认证授权需求
    • 4.3 分布式认证授权方案
    • 4.3.1 基于session的认证方式
    • 4.3.2 基于token的认证方式
    • 4.3.3 技术选型
  • 5.Spring Security OAuth2
    • 5.1 OAuth2.0简介
    • 5.2 Spring Security OAuth2
    • 5.3 JWT令牌
      • 5.3.1 JWT介绍
  • 6.spring security分布式系统授权
    • 6.1 系统架构
    • 6.2 初始化环境
    • 6.3 项目架构
    • 6.4 项目地址
    • 6.5 测试脚本idea httpclient

1. 基本概念

1.1 什么是认证

认证:用户认证就是判断一个用户的身份是否合法的过程,用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录,二维码登录,手机短信登录,指纹人脸识别认证等方式。

1.2 什么是会话

用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中。会话就是系统为了保持当前用户的登录状态所提供的机制,常见的有基于session方式、基于token方式等。

基于session的认证方式如下图:

它的交互流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的sesssion_id 存放到cookie 中,这样用户客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户的合法校验,当用户退出系统或session过期销毁时,客户端的session_id也就无效了。

token也是类似的。

1.3 什么是授权

认证是为了保证用户身份的合法性,授权则是为了更细粒度的对隐私数据进行划分,授权是在认证通过后发生的,控制不同的用户能够访问不同的资源。

授权: 授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。

1.4 授权数据模型

1.4.1 授权认证流程

1.4.2 ER关系模型

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

1.5 RBAC

如何实现授权?业界通常基于RBAC实现授权。两种方式:

RBAC基于角色的访问控制(Role-Based Access Control)是按角色进行授权,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等。

RBAC基于资源的访问控制(Resource-Based Access Control)是按资源(或权限)进行授权,比如:用户必须具有查询工资权限才可以查询员工工资信息等。

2. 基于session的认证方式

2.1 基于session认证流程

基于Session认证方式的流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话),而发给客户端的 sesssion_id 存放到cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在session 数据,以此完成用户的合法校验。当用户退出系统或session过期销毁时,客户端的session_id也就无效了。

下图是session认证方式的流程图:

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

2.2 基于session总结

基于session的认证方式目前不常用了,而且不适用于现在分布式微服务场景,这里就不再展开讲解,详情百度吧。

在正式生产项目中,我们往往会考虑使用第三方安全框架(如 spring security,shiro等安全框架)来实现认证授权功能,因为这样做能一定程度提高生产力,提高软件标准化程度,另外往往这些框架的可扩展性考虑的非常全面。但是缺点也非常明显,这些通用化组件为了提高支持范围会增加很多可能我们不需要的功能,结构上也会比较抽象,如果我们不够了解它,一旦出现问题,将会很难定位。

3. spring security原理分析

3.1 结构总览

Spring Security所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截,校验每个请求是否能够访问它所期望的资源。根据前边知识的学习,可以通过Filter或AOP等技术来实现,SpringSecurity对Web资源的保护是靠Filter实现的,所以从这个Filter来入手,逐步深入Spring Security原理。

当初始化Spring Security时,会创建一个名为 SpringSecurityFilterChain 的Servlet过滤器,类型为org.springframework.security.web.FilterChainProxy,它实现了javax.servlet.Filter,因此外部的请求会经过此类,下图是Spring Security过虑器链结构图:

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

FilterChainProxy是一个代理,真正起作用的是 Security核心,各有各的职责,但他们并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和决策管理器(AccessDecisionManager)进行处理,下图是FilterChainProxy相关类的UML图示。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权
spring Security功能的实现主要是由一系列过滤器链相互配合完成。
           
微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权
下面介绍过滤器链中主要的几个过滤器及其作用:
SecurityContextPersistenceFilter 这个Filter是整个拦截过程的入口和出口(也就是第一个和最后一个拦截器),会在请求开始时从配置好的SecurityContextRepository 中获取 SecurityContext,然后把它设置给SecurityContextHolder。在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,同时清除 securityContextHolder 所持有的 SecurityContext;

UsernamePasswordAuthenticationFilter 用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,其内部还有登录成功或失败后进行处理的 AuthenticationSuccessHandler 和AuthenticationFailureHandler,这些都可以根据需求做相关改变;

FilterSecurityInterceptor是用于保护web资源的,使用AccessDecisionManager 对当前用户进行授权访问,前面已经详细介绍过了;

ExceptionTranslationFilter 能够捕获来自 FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:AuthenticationException 和 AccessDeniedException,其它的异常它会继续抛出。
           

3.2 认证流程

3.2.1 认证流程

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

让我们仔细分析认证过程:

  1. 用户提交用户名、密码被SecurityFilterChain中的UsernamePasswordAuthenticationFilter 过滤器获取到,封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
  2. 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证。
  3. 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除) Authentication 实例。
  4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个List 列表,存放多种认证方式,最终实际的认证工作是由AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终AuthenticationProvider将UserDetails填充至Authentication。

    认证核心组件的大体关系如下:

    微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

3.2.2 AuthenticationProvider

通过前面的Spring Security认证流程我们得知,认证管理器(AuthenticationManager)委托AuthenticationProvider完成认证工作。

3.2.3 UserDetailsService

DaoAuthenticationProvider中包含了一个UserDetailsService实例,它负责根据用户名提取用户信息UserDetails(包含密码),而后DaoAuthenticationProvider会去对比UserDetailsService提取的用户密码与用户提交的密码是否匹配作为认证成功的关键依据,因此可以通过将自定义的 UserDetailsService 公开为spring bean来定义自定义身份验证。

3.2.4 PasswordEncoder

在这里Spring Security为了适应多种多样的加密类型,又做了抽象,DaoAuthenticationProvider通过PasswordEncoder接口的matches方法进行密码的对比,而具体的密码对比细节取决于实现。

3.3 授权流程

3.3.1 授权流程

Spring Security可以通过 http.authorizeRequests() 对web请求进行授权保护。SpringSecurity使用标准Filter建立了对web请求的拦截,最终实现对资源的授权访问。

Spring Security的授权流程如下:

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

分析授权流程:

  1. 拦截请求,已认证用户访问受保护的web资源将被SecurityFilterChain中的 FilterSecurityInterceptor 的子类拦截。
  2. 获取资源访问策略,FilterSecurityInterceptor会从 SecurityMetadataSource 的子类DefaultFilterInvocationSecurityMetadataSource 获取要访问当前资源所需要的权限Collection 。SecurityMetadataSource其实就是读取访问策略的抽象,而读取的内容,其实就是我们配置的访问规则。
  3. 最后,FilterSecurityInterceptor会调用 AccessDecisionManager 进行授权决策,若决策通过,则允许访问资源,否则将禁止访问。

3.3.1 授权决策

AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

通过上图可以看出,AccessDecisionManager中包含的一系列AccessDecisionVoter将会被用来对Authentication是否有权访问受保护对象进行投票,AccessDecisionManager根据投票结果,做出最终决策。

Spring Security内置了三个基于投票的AccessDecisionManager实现类如下,它们分别是AffirmativeBased、ConsensusBased和UnanimousBased。

AffirmativeBased的逻辑是:
(1)只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;
(2)如果全部弃权也表示通过;
(3)如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException。
Spring security默认使用的是AffirmativeBased。

ConsensusBased的逻辑是:
(1)如果赞成票多于反对票则表示通过。
(2)反过来,如果反对票多于赞成票则将抛出AccessDeniedException。
(3)如果赞成票与反对票相同且不等于0,并且属性allowIfEqualGrantedDeniedDecisions的值为true,则表示通过,否则将抛出异常AccessDeniedException。参数allowIfEqualGrantedDeniedDecisions的值默认为true。
(4)如果所有的AccessDecisionVoter都弃权了,则将视参数allowIfAllAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常AccessDeniedException。参数allowIfAllAbstainDecisions的值默认为false。

UnanimousBased的逻辑与另外两种实现有点不一样,另外两种会一次性把受保护对象的配置属性全部传递给AccessDecisionVoter进行投票,而UnanimousBased会一次只传递一个ConfigAttribute给AccessDecisionVoter进行投票。这也就意味着如果我们的AccessDecisionVoter的逻辑是只要传递进来的ConfigAttribute中有一个能够匹配则投赞成票,但是放到UnanimousBased中其投票结果就不一定是赞成了。

UnanimousBased的逻辑具体来说是这样的:
(1)如果受保护对象配置的某一个ConfigAttribute被任意的AccessDecisionVoter反对了,则将抛出AccessDeniedException。
(2)如果没有反对票,但是有赞成票,则表示通过。
(3)如果全部弃权了,则将视参数allowIfAllAbstainDecisions的值而定,true则通过,false则抛出AccessDeniedException。

Spring Security也内置一些投票者实现类如RoleVoter、AuthenticatedVoter和WebExpressionVoter等,可以自行查阅资料进行学习。

           

4.分布式系统认证方案

4.1分布式架构

随着软件环境和需求的变化,软件架构由单体应用逐渐演变为分布式微服务架构。服务之间调用错综复杂,统一应用,统一数据必不可少,spring security解决的就是统一鉴权。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

4.2 分布式认证授权需求

分布式系统的每个服务都会有认证、授权的需求,如果每个服务都实现一套认证授权逻辑会非常冗余,考虑分布式系统共享性的特点,需要由独立的认证服务处理系统认证授权的请求;考虑分布式系统开放性的特点,不仅对系统内部服务提供认证,对第三方系统也要提供认证。分布式认证的需求总结如下:

统一认证授权
提供独立的认证服务,统一处理认证授权。
无论是不同类型的用户,还是不同种类的客户端(web端,H5、APP),均采用一致的认证、权限、会话机制,实现统一认证授权。
要实现统一则认证方式必须可扩展,支持各种认证需求,比如:用户名密码认证、短信验证码、二维码、人脸识别认证方式,并可以非常灵活的切换。

应用接入认证
应提供扩展和开放能力,提供安全的系统对接机制,并可开放部分API给接入第三方使用,一方应用(内部 系统服务)和三方应用(第三方应用)均采用统一机制接入。
           

4.3 分布式认证授权方案

4.3.1 基于session的认证方式

在分布式的环境下,基于session的认证会出现一个问题,每个应用服务都需要在session中存储用户身份信息,通过负载均衡将本地的请求分配到另一个应用服务需要将session信息带过去,否则会重新认证。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

解决方案

这个时候,通常的做法有下面几种:
Session复制:多台应用服务器之间同步session,使session保持一致,对外透明。
Session黏贴:当用户访问集群中某台服务器后,强制指定后续所有请求均落到此机器上。
Session集中存储:将Session存入分布式缓存中,所有服务器应用实例统一从分布式缓存中存取Session。

总体来讲,基于session认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高。但是,session机制方式基于cookie,在复杂多样的移动客户端上不能有效的使用,并且无法跨域,另外随着系统的扩展需提高session的复制、黏贴及存储的容错性。
           

4.3.2 基于token的认证方式

基于token的认证方式,服务端不用存储认证数据,易维护扩展性强, 客户端可以把token 存在任意地方,并且可以实现web和app统一认证机制。其缺点也很明显,token由于自包含信息,因此一般数据量较大,而且每次请求都需要传递,因此比较占带宽。另外,token的签名验签操作也会给cpu带来额外的处理负担。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

4.3.3 技术选型

一般有两种方式:基于session与基于token认证授权。

总体来讲,基于session认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高。但是,session机制方式基于cookie,在复杂多样的移动客户端上不能有效的使用,并且无法跨域,另外随着系统的扩展需提高session的复制、黏贴及存储的容错性。

选型分析,决定采用基于token的认证方式,它的优点是:

1、适合统一认证的机制,客户端、一方应用、三方应用都遵循一致的认证机制。

2、token认证方式对第三方应用接入更适合,因为它更开放,可使用当前有流行的开放协议Oauth2.0、JWT等。

3、一般情况服务端无需存储会话信息,减轻了服务端的压力。

分布式系统认证技术方案见下图

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

5.Spring Security OAuth2

5.1 OAuth2.0简介

OAuth2.0是标准协议。

Spring Security OAuth是基于OAuth标准协议落地的安全框架。

OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。很多大公司如Google,Yahoo,Microsoft等都提供了OAUTH认证服务,这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。

Oauth协议目前发展到2.0版本,1.0版本过于复杂,2.0版本已得到广泛应用。

百度百科:https://baike.baidu.com/item/oAuth/7153134?fr=aladdin

Oauth协议:https://tools.ietf.org/html/rfc6749

5.2 Spring Security OAuth2

官网地址:https://docs.spring.io/spring-security/site/docs/current/reference/html5/

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

官方GitHub地址:https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Migration-Guide

官网各种案例写的还是很清楚的,可以参考学习。

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

Spring-Security-OAuth2是对OAuth2的一种实现,并且跟我们之前学习的Spring Security相辅相成,与SpringCloud体系的集成也非常便利,接下来,我们需要对它进行学习,最终使用它来实现我们设计的分布式认证授权解决方案。

OAuth2.0的服务提供方涵盖两个服务,即授权服务(Authorization Server,也叫认证服务) 和资源服务(ResourceServer),使用 Spring Security OAuth2 的时候你可以选择把它们在同一个应用程序中实现,也可以选择建立使用同一个授权服务的多个资源服务。

授权服务 (Authorization Server)应包含对接入端以及登入用户的合法性进行验证并颁发token等功能,对令牌的请求端点由 Spring MVC 控制器进行实现,下面是配置一个认证服务必须要实现的endpoints:

AuthorizationEndpoint 服务于认证请求。默认 URL:/oauth/authorize 。

TokenEndpoint 服务于访问令牌的请求。默认 URL:/oauth/token 。

资源服务 (Resource Server),应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务:

OAuth2AuthenticationProcessingFilter用来对请求给出的身份令牌解析鉴权。

本教程分别创建uaa授权服务(也可叫认证服务)和order订单资源服务。

5.3 JWT令牌

先抛个问题吧
普通令牌有什么问题,为什么会出现JWT,JWT是什么

普通令牌问题
普通令牌通过测试可以发现,当资源服务与授权服务不在一起时,每次请求资源服务使用RemoteTokenServices远程请求授权验证token,如果访问量较大将会影响系统性能。

解决方案
令牌采用JWT格式即可解决上述问题,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端每次访问服务资源只需要携带JWT即可,资源服务根据实现约定的算法自行完成令牌校验,无需每次都请求验证完成授权。

           

5.3.1 JWT介绍

  1. 什么是JWT

    JSON Web Token(JWT)是一个开放的行业标准(RFC7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。

    官网:https://jwt.io/

    标准:https://tools.ietf.org/html/rfc7519

  2. JWT优缺点

    JWT令牌的优点:

    1)jwt基于json,非常方便解析。

    2)可以在令牌中自定义丰富的内容,易扩展。

    3)通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。

    4)资源服务使用JWT可不依赖认证服务即可完成授权。

    缺点:

    1)JWT令牌较长,占存储空间比较大。

  3. JWT令牌结构

    JWT令牌由三部分组成,每部分中间使用点(.)分隔,Header, Payload,Signature。比如:xxxxx.yyyyy.zzzzz

Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)

Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。

Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明签名算法进行签名。

           

6.spring security分布式系统授权

6.1 系统架构

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

6.2 初始化环境

-- 创建user_db数据库
-- 创建7张表,user,user_role,role,role_permission,permission,oauth_code,oauth_client_details
-- ----------------------------
/*
 Navicat Premium Data Transfer

 Source Server         : mysql-root
 Source Server Type    : MySQL
 Source Server Version : 50727
 Source Host           : localhost:3306
 Source Schema         : user_db

 Target Server Type    : MySQL
 Target Server Version : 50727
 File Encoding         : 65001

 Date: 27/06/2021 17:21:59
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for oauth_client_details
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details`  (
  `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端标识',
  `resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接入资源列表',
  `client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端秘钥',
  `scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `access_token_validity` int(11) NULL DEFAULT NULL,
  `refresh_token_validity` int(11) NULL DEFAULT NULL,
  `additional_information` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
  `archived` tinyint(4) NULL DEFAULT NULL,
  `trusted` tinyint(4) NULL DEFAULT NULL,
  `autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`client_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '接入客户端信息' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('c1', 'res1', '$2a$10$RxcatifU8i6q3uwaG1mdWuObAJZr99YSnDdP5aNpMJVfUVrX4XQYO', 'ROLE_ADMIN,ROLE_USER,ROLE_API', 'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', '', 7200, 259200, NULL, '2021-06-26 14:34:06', 0, 0, 'false');
INSERT INTO `oauth_client_details` VALUES ('c2', 'res2', 'secret', 'ROLE_API', 'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com', '', 7200, 259200, NULL, '2021-06-26 14:25:42', 0, 0, 'false');

-- ----------------------------
-- Table structure for oauth_code
-- ----------------------------
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code`  (
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `authentication` blob NULL,
  INDEX `code_index`(`code`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of oauth_code
-- ----------------------------
INSERT INTO `oauth_code` VALUES ('2021-06-26 14:47:56', '5zSayS', 0xACED0005737200416F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F417574683241757468656E7469636174696F6EBD400B02166252130200024C000D73746F7265645265717565737474003C4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F4F4175746832526571756573743B4C00127573657241757468656E7469636174696F6E7400324C6F72672F737072696E676672616D65776F726B2F73656375726974792F636F72652F41757468656E7469636174696F6E3B787200476F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E416273747261637441757468656E7469636174696F6E546F6B656ED3AA287E6E47640E0200035A000D61757468656E746963617465644C000B617574686F7269746965737400164C6A6176612F7574696C2F436F6C6C656374696F6E3B4C000764657461696C737400124C6A6176612F6C616E672F4F626A6563743B787000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C6973747400104C6A6176612F7574696C2F4C6973743B7872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C00016371007E00047870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000002770400000002737200426F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E617574686F726974792E53696D706C654772616E746564417574686F7269747900000000000001FE0200014C0004726F6C657400124C6A6176612F6C616E672F537472696E673B787074000270317371007E000D74000270337871007E000C707372003A6F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E4F41757468325265717565737400000000000000010200075A0008617070726F7665644C000B617574686F72697469657371007E00044C000A657874656E73696F6E7374000F4C6A6176612F7574696C2F4D61703B4C000B726564697265637455726971007E000E4C00077265667265736874003B4C6F72672F737072696E676672616D65776F726B2F73656375726974792F6F61757468322F70726F76696465722F546F6B656E526571756573743B4C000B7265736F7572636549647374000F4C6A6176612F7574696C2F5365743B4C000D726573706F6E7365547970657371007E0016787200386F72672E737072696E676672616D65776F726B2E73656375726974792E6F61757468322E70726F76696465722E426173655265717565737436287A3EA37169BD0200034C0008636C69656E74496471007E000E4C001172657175657374506172616D657465727371007E00144C000573636F706571007E001678707400026331737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654D6170F1A5A8FE74F507420200014C00016D71007E00147870737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F400000000000067708000000080000000474000D726573706F6E73655F74797065740004636F646574000C72656469726563745F757269740014687474703A2F2F7777772E62616964752E636F6D740009636C69656E745F696471007E001974000573636F706574000A524F4C455F41444D494E78737200256A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65536574801D92D18F9B80550200007871007E0009737200176A6176612E7574696C2E4C696E6B656448617368536574D86CD75A95DD2A1E020000787200116A6176612E7574696C2E48617368536574BA44859596B8B7340300007870770C000000103F4000000000000171007E002478017371007E0028770C000000103F40000000000000787371007E001C3F400000000000007708000000100000000078740014687474703A2F2F7777772E62616964752E636F6D707371007E0028770C000000103F4000000000000174000472657331787371007E0028770C000000103F4000000000000171007E001F787372004F6F72672E737072696E676672616D65776F726B2E73656375726974792E61757468656E7469636174696F6E2E557365726E616D6550617373776F726441757468656E7469636174696F6E546F6B656E00000000000001FE0200024C000B63726564656E7469616C7371007E00054C00097072696E636970616C71007E00057871007E0003017371007E00077371007E000B0000000277040000000271007E000F71007E00117871007E0033737200486F72672E737072696E676672616D65776F726B2E73656375726974792E7765622E61757468656E7469636174696F6E2E57656241757468656E7469636174696F6E44657461696C7300000000000001FE0200024C000D72656D6F74654164647265737371007E000E4C000973657373696F6E496471007E000E787074000F303A303A303A303A303A303A303A31740020324136454436363739433944443037423339364232314641314435463832384270737200326F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657200000000000001FE0200075A00116163636F756E744E6F6E457870697265645A00106163636F756E744E6F6E4C6F636B65645A001563726564656E7469616C734E6F6E457870697265645A0007656E61626C65644C000B617574686F72697469657371007E00164C000870617373776F726471007E000E4C0008757365726E616D6571007E000E7870010101017371007E0025737200116A6176612E7574696C2E54726565536574DD98509395ED875B0300007870737200466F72672E737072696E676672616D65776F726B2E73656375726974792E636F72652E7573657264657461696C732E5573657224417574686F72697479436F6D70617261746F7200000000000001FE020000787077040000000271007E000F71007E001178707400957B2266756C6C6E616D65223A22E5BCA0E4B889222C226964223A2231222C226D6F62696C65223A223133303537363331323339222C2270617373776F7264223A22243261243130246146734F467A756A7450436E5543554B636F7A734875783072512F3366614148474653566239592E42316E74706D45686A52747275222C22757365726E616D65223A227A68616E6773616E227D);

-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限标识符',
  `description` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  `url` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', 'p1', '测试资源1', '/r/r1');
INSERT INTO `permission` VALUES ('2', 'p3', '测试资源2', '/r/r2');

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `update_time` datetime(0) NULL DEFAULT NULL,
  `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `unique_role_name`(`role_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', '管理员', '系统管理员', '2021-06-20 17:35:40', '2021-06-20 17:35:44', '1');

-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission`  (
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES ('1', '1');
INSERT INTO `role_permission` VALUES ('1', '2');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(20) NOT NULL COMMENT '用户id',
  `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `fullname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户姓名',
  `mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'zhangsan', '$2a$10$aFsOFzujtPCnUCUKcozsHux0rQ/3faAHGFSVb9Y.B1ntpmEhjRtru', '张三', '13057631239');
INSERT INTO `user` VALUES (2, 'lisi', '$2a$10$aFsOFzujtPCnUCUKcozsHux0rQ/3faAHGFSVb9Y.B1ntpmEhjRtru', '李四', '13301610396');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (
  `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `creator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1', '2021-06-20 17:37:05', 'jerry');

SET FOREIGN_KEY_CHECKS = 1;
           

6.3 项目架构

父工程:distributed-security

子工程Model:鉴权服务distributed-security-uaa

子工程Model:订单服务distributed-security-order

子工程Model:注册中心服务distributed-security-discovery

子工程Model:网关服务distributed-security-gateway

微服务 Spring Security OAuth2.0认证授权1. 基本概念2. 基于session的认证方式3. spring security原理分析4.分布式系统认证方案5.Spring Security OAuth26.spring security分布式系统授权

6.4 项目地址

gitee地址:https://gitee.com/rjzhu/distributed-security

文档,初始化脚本,测试脚本都放上去了,自行查看。

本来想放GitHub的,奈何挂了,访问不了,而且平时速度相比于gitee也慢,替gitee打一波小广告,gitee是真的速度很快,还支持中文,主要是稳定,不得不说gitee真香。

6.5 测试脚本idea httpclient

### idea httpclient 
### spring security 认证授权四种模式

### 获取授权码,申请授权码,浏览器打开,然后选择授权Approve,授权码:https://www.baidu.com/?code=BvnSwc
POST http://localhost:53020/uaa/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com

### 获取授权码,基于数据库存储
POST http://localhost:53020/uaa/oauth/authorize?client_id=c1&response_type=code&scope=ROLE_ADMIN&redirect_uri=http://www.baidu.com

### 1.授权码模式,通过授权码获取token信息,授权码只能使用一次
POST http://localhost:53020/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=G4whQf&redirect_uri=http://www.baidu.com
Accept: */*
Cache-Control: no-cache

### 2.简化模式,浏览器打开,然后选择授权Approve,获取token信息
### https://www.baidu.com/#access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJ7XCJmdWxsbmFtZVwiOlwi5byg5LiJXCIsXCJpZFwiOlwiMVwiLFwibW9iaWxlXCI6XCIxMzA1NzYzMTIzOVwiLFwicGFzc3dvcmRcIjpcIiQyYSQxMCRhRnNPRnp1anRQQ25VQ1VLY296c0h1eDByUS8zZmFBSEdGU1ZiOVkuQjFudHBtRWhqUnRydVwiLFwidXNlcm5hbWVcIjpcInpoYW5nc2FuXCJ9Iiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTYyNDY3ODM5NCwiYXV0aG9yaXRpZXMiOlsicDEiLCJwMyJdLCJqdGkiOiJiNjVmMDI2Ni1lZmVkLTRjOWYtYWY5Yi1hOTlkZDg5NzNhODkiLCJjbGllbnRfaWQiOiJjMSJ9.fMcGIg7uzxecksrr-ck7PqPD9yiUsBYvRUc3SFpAKgk&token_type=bearer&expires_in=6789&jti=b65f0266-efed-4c9f-af9b-a99dd8973a89
POST http://localhost:53020/uaa/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com

### 3.密码模式,获取access_token
# 直接调用资源服务即uaa服务,uaa认证授权
#POST http://localhost:53020/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123
# 通过网关调用资源服务即调用gateway服务,uaa认证授权
POST http://localhost:53010/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123
Accept: */*
Cache-Control: no-cache

### 4.客户端模式,获取access_token
POST http://localhost:53020/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials
Accept: */*
Cache-Control: no-cache

### check_token验证
POST http://localhost:53020/uaa/oauth/check_token?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJ7XCJmdWxsbmFtZVwiOlwi5byg5LiJXCIsXCJpZFwiOlwiMVwiLFwibW9iaWxlXCI6XCIxMzA1NzYzMTIzOVwiLFwicGFzc3dvcmRcIjpcIiQyYSQxMCRhRnNPRnp1anRQQ25VQ1VLY296c0h1eDByUS8zZmFBSEdGU1ZiOVkuQjFudHBtRWhqUnRydVwiLFwidXNlcm5hbWVcIjpcInpoYW5nc2FuXCJ9Iiwic2NvcGUiOlsiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiIsIlJPTEVfQVBJIl0sImV4cCI6MTYyNDc2MTMyMywiYXV0aG9yaXRpZXMiOlsicDEiLCJwMyJdLCJqdGkiOiI5ZGM4MDFlOC01NDY0LTQ1ODEtYjJmNi01MTU5NzJmOTNlOWYiLCJjbGllbnRfaWQiOiJjMSJ9.h7rD-wpDysTlq8RqYXpSJ8mM-llWTv0rnnw0IutUPBM
Accept: */*
Cache-Control: no-cache

### 资源权限,必须是正确,且有权限的用户获取的token信息才能访问人、r1资源
# 直接调用资源服务,即order服务
#GET http://localhost:53021/order/r1
# 通过网关调用资源服务,即调用gateway服务
GET http://localhost:53010/order/r1
Accept: */*
Cache-Control: no-cache
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJ7XCJmdWxsbmFtZVwiOlwi5byg5LiJXCIsXCJpZFwiOlwiMVwiLFwibW9iaWxlXCI6XCIxMzA1NzYzMTIzOVwiLFwicGFzc3dvcmRcIjpcIiQyYSQxMCRhRnNPRnp1anRQQ25VQ1VLY296c0h1eDByUS8zZmFBSEdGU1ZiOVkuQjFudHBtRWhqUnRydVwiLFwidXNlcm5hbWVcIjpcInpoYW5nc2FuXCJ9Iiwic2NvcGUiOlsiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiIsIlJPTEVfQVBJIl0sImV4cCI6MTYyNDc2MTMyMywiYXV0aG9yaXRpZXMiOlsicDEiLCJwMyJdLCJqdGkiOiI5ZGM4MDFlOC01NDY0LTQ1ODEtYjJmNi01MTU5NzJmOTNlOWYiLCJjbGllbnRfaWQiOiJjMSJ9.h7rD-wpDysTlq8RqYXpSJ8mM-llWTv0rnnw0IutUPBM

###






           

继续阅读