Spring-Security-BASE-3

Spring Security 基础 3

转载:https://blog.csdn.net/REX1129/article/details/114589484

源码下载: 下载

SpringSecurity 微服务权限方案

1. 什么是微服务

1、微服务由来

微服务最早由 Martin Fowler 与 James Lewis 于 2014 年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTPAPI,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。

2、微服务优势

(1)微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比
较好解决。
(2)微服务每个模块都可以使用不同的存储方式(比如有的用 redis,有的用 mysql
等),数据库也是单个模块对应自己的数据库。
(3)微服务每个模块都可以使用不同的开发技术,开发模式更灵活。

3、微服务本质

(1)微服务,关键其实不仅仅是微服务本身,而是系统要提供一套基础的架构,这种架构
使得微服务可以独立的部署、运行、升级,不仅如此,这个系统架构还让微服务与微服务
之间在结构上“松耦合”,而在功能上则表现为一个统一的整体。这种所谓的“统一的整
体”表现出来的是统一风格的界面,统一的权限管理,统一的安全策略,统一的上线过
程,统一的日志和审计方法,统一的调度方式,统一的访问入口等等。
(2)微服务的目的是有效的拆分应用,实现敏捷开发和部署。

2 微服务认证与授权实现思路

2.1 认证授权过程分析

(1)如果是基于 Session,那么 Spring-security 会对 cookie 里的 sessionid 进行解析,找到服务器存储的 session 信息,然后判断当前用户是否符合请求的要求。
(2)如果是 token,则是解析出 token,然后将当前请求加入到 Spring-security 管理的权限信息中去

如果系统的模块众多,每个模块都需要进行授权与认证,所以我们选择基于 token 的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为 key,权限列表为 value 的形式存入 redis缓存中,根据用户名相关信息生成 token 返回,浏览器将 token 记录到 cookie 中,每次调用 api 接口都默认将 token 携带到 header 请求头中,Spring-security 解析 header 头获取 token 信息,解析 token 获取当前用户名,根据用户名就可以从 redis 中获取权限列表,这样 Spring-security 就能够判断当前请求是否有权限访问

2.2 权限管理数据模型

2.3 jwt 介绍

官网:https://jwt.io/

2.3.1 访问令牌的类型

透明令牌(By reference token)

随机生成的字符串标识符,无法简单猜测授权服务器如何颁发和存储
资源服务器必须通过后端渠道发送回OAuth2授权服务器的令牌检查端点,才能效验令牌是否有效,并获取claims/scopes等额外信息

自包含令牌(By value token)

授权服务器颁发的令牌,包含关于用户或者客户的元数据和声明(claims)
通过检查签名,期望的颁发者(issuer),期望的接收人aud(audience),或者scope,资源服务器可以在本地效验令牌通常实现为签名的JSON Web Tokens(JWT)

2.3.2 JWT 的组成

典型的,一个 JWT 看起来如下图:

base64url(Header) + "." +
base64url(Claims) + "." +
base64url(Signature)

该对象为一个很长的字符串,字符之间通过”.”分隔符分为三个子串。
每一个子串表示了一个功能块,总共有以下三个部分:JWT 头、有效载荷和签名

JWT 头

JWT 头部分是一个描述 JWT 元数据的 JSON 对象,通常如下所示。

{
    "alg": "HS256",
    "typ": "JWT"
}

在上面的代码中,alg 属性表示签名使用的算法,默认为 HMAC SHA256(写为 HS256);typ 属性表示令牌的类型,JWT 令牌统一写为 JWT。最后,使用 Base64 URL 算法将上述JSON 对象转换为字符串保存。

有效载荷

有效载荷部分,是 JWT 的主体内容部分,也是一个 JSON 对象,包含需要传递的数据。 JWT
指定七个默认字段供选择。

iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID 用于标识该 JWT

除以上默认字段外,我们还可以自定义私有字段,如下例:

{
    "sub": "1234567890",
    "name": "Sevattal",
    "admin": true
}

请注意,默认情况下 JWT 是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

JSON 对象也使用 Base64 URL 算法转换为字符串保存。

签名哈希

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为 HMAC SHA256)根据以下公式生成
签名。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret)

在计算出签名哈希后,JWT 头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用”.”分隔,就构成整个 JWT 对象。

Base64URL 算法

如前所述,JWT 头和有效载荷序列化的算法都用到了 Base64URL。该算法和常见 Base64 算法类似,稍有差别。

作为令牌的 JWT 可以放在 URL 中(例如 api.example/?token=xxx)。 Base64 中用的三个字符是”+”,”/“和”=”,由于在 URL 中有特殊含义,因此 Base64URL 中对他们做了替换:”=”去掉,”+”用”-“替换,”/“用”_”替换,这就是 Base64URL 算法。

2.4 具体代码实现

案例涉及技术说明

Java技术

1.Maven:创建父工程:管理项目依赖版本,创建子模块:使用具体依赖
2.Spring Boot:本质就是Spring
3.MyBatisPlus 操作数据库框架
4.Spring Cloud:
(1)Gateway 网关
(2)注册中心 Nacos

其他技术:

1.Redis (用于缓存token令牌)
2.Jwt (Token令牌生成)
3.Swagger (接口文档)
4.前端技术(vue-element-ui-admin)

2.4.1 搭建项目工程

创建父工程 acl_parent:管理依赖版本
在父工程创建子模块
(1)common
* service_base:权限配置
* spring_security:权限配置
(2)infrastructure
* api_gateway:网关
(3)service
* service_acl:权限管理微服务模块

2.4.2 整合网关和前端

1.网关:

修改api_gateway/application.properties中mysql、redis参数

2. 前端(使用的 vue-element-admin 前端平台)

修改 config/dev.env.js、login.js 参数

BASE_API: '"http://localhost:8222"'

url: '/admin/acl/login'
url: '/admin/acl/index/info'
url: '/admin/acl/index/logout'
url: '/admin/acl/index/menu'

2.4.3 启动测试

1. 启动Redis
2. 启动Nacos
3. 启动后端 api_gateway、service_acl
4. 启动前端: npm run dev
5. 访问:用户名 admin、密码 111111

2.4.3 认证流程详解

1.UsernamePasswordAuthenticationFilter

(1)第一步 过滤的方法,判断提交方式是否是post提交 AbstractAuthenticationProcessingFilter.doFilter
(2)第二步 调用子类的方法进行身份认证 认证成功之后把认证信息封装到对象里面 Authentication
    UsernamePasswordAuthenticationFilter.attemptAuthentication 方法
    子类中 attemptAuthentication 方法:判断post请求,获取提交的用户名密码、构造成对象标记为未认证,把请求一些属性信息设置到对象里,调用方法进行身份认证(调用userDetailsService)
(3)第三步 session策略处理 sessionStrategy.onAuthentication
(4)第四步
    1 认证失败抛出异常,执行认证失败的方法 unsuccessfulAuthentication
    ExceptionTranslactionFilter
    2 认证成功,调用认证成功的方法 successfulAuthentication

2.ProviderManager

2.4.4 权限访问流程详解

ExceptionTranslationFilter过滤器和FilterSecurityInterceptor过滤器

1.ExceptionTranslationFilter

(1)前端请求,直接放行
(2)如果抛出异常,进行捕获,进行处理

FilterSecurityInterceptor

(1)判断请求是否有权限
(2)进行springmvc处理

2.4.5 认证信息共享

(1)认证成功的方法,把认证信息对象方法对象中 successfulAuthentication

SecurityContextHolder.getContext().setAuthentication(authResult);

(2)SecurityContext对象
对Authentication进行封装

(3)SecurityContextHolder
使用ThreadLocal和线程绑定

(4)SecurityContextPersistenceFilter

Contents
  1. 1. Spring Security 基础 3
    1. 1.1. SpringSecurity 微服务权限方案
      1. 1.1.1. 1. 什么是微服务
        1. 1.1.1.1. 1、微服务由来
        2. 1.1.1.2. 2、微服务优势
        3. 1.1.1.3. 3、微服务本质
      2. 1.1.2. 2 微服务认证与授权实现思路
        1. 1.1.2.1. 2.1 认证授权过程分析
      3. 1.1.3. 2.2 权限管理数据模型
      4. 1.1.4. 2.3 jwt 介绍
        1. 1.1.4.1. 2.3.1 访问令牌的类型
        2. 1.1.4.2. 2.3.2 JWT 的组成
          1. 1.1.4.2.1. JWT 头
          2. 1.1.4.2.2. 有效载荷
          3. 1.1.4.2.3. 签名哈希
          4. 1.1.4.2.4. Base64URL 算法
      5. 1.1.5. 2.4 具体代码实现
        1. 1.1.5.1. 2.4.1 搭建项目工程
          1. 1.1.5.1.1. 创建父工程 acl_parent:管理依赖版本
          2. 1.1.5.1.2. 在父工程创建子模块
        2. 1.1.5.2. 2.4.2 整合网关和前端
          1. 1.1.5.2.1. 1.网关:
          2. 1.1.5.2.2. 2. 前端(使用的 vue-element-admin 前端平台)
        3. 1.1.5.3. 2.4.3 启动测试
      6. 1.1.6. 2.4.3 认证流程详解
      7. 1.1.7. 2.4.4 权限访问流程详解
      8. 1.1.8. 2.4.5 认证信息共享
|