Spring Cloud实战系列(十) - 单点登录JWT与Spring Security OAuth 2.0

本文介绍了如何使用JWT和Spring Security OAuth 2.0实现Spring Cloud的单点登录。详细讲解了JWT的结构、工作方式,并通过实例展示了授权服务和资源服务的构建过程,包括授权服务发放JWT、资源服务验证JWT的过程。通过这种方式,资源服务可以减少对授权服务的依赖,提高系统效率。
摘要由CSDN通过智能技术生成

前言

通过 JWT 配合 Spring Security OAuth2 使用的方式,可以避免 每次请求远程调度 认证授权服务。资源服务器 只需要从 授权服务器 验证一次,返回 JWT。返回的 JWT 包含了 用户 的所有信息,包括 权限信息

正文

1. 什么是JWT

JSON Web TokenJWT)是一种开放的标准(RFC 7519),JWT 定义了一种 紧凑自包含 的标准,旨在将各个主体的信息包装为 JSON 对象。主体信息 是通过 数字签名 进行 加密验证 的。经常使用 HMAC 算法或 RSA公钥/私钥非对称性加密)算法对 JWT 进行签名,安全性很高

  • 紧凑型数据体积小,可通过 POST 请求参数HTTP 请求头 发送。

  • 自包含JWT 包含了主体的所有信息,避免了 每个请求 都需要向 Uaa 服务验证身份,降低了 服务器的负载

2. JWT的结构

JWT 的结构由三部分组成:Header(头)、Payload(有效负荷)和 Signature(签名)。因此 JWT 通常的格式是 xxxxx.yyyyy.zzzzz

2.1. Header

Header 通常是由 两部分 组成:令牌的 类型(即 JWT)和使用的 算法类型,如 HMACSHA256RSA。例如:

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

HeaderBase64 编码作为 JWT第一部分,不建议在 JWTHeader 中放置 敏感信息

2.2. Payload

第二部分 PayloadJWT主体内容部分,它包含 声明 信息。声明是关于 用户其他数据 的声明。

声明有三种类型: registeredpublicprivate

  • Registered claimsJWT 提供了一组 预定义 的声明,它们不是 强制的,但是推荐使用。JWT 指定 七个默认 字段供选择:
注册声明 字段含义
iss 发行人
exp 到期时间
sub 主题
aud 用户
nbf 在此之前不可用
iat 发布时间
jti 用于标识JWT的ID
  • Public claims:可以随意定义。

  • Private claims:用于在 同意使用 它们的各方之间 共享信息,并且不是 注册的公开的 声明。

下面是 Payload 部分的一个示例:

{
   
    "sub": "123456789",
    "name": "John Doe",
    "admin": true
}

PayloadBase64 编码作为 JWT第二部分,不建议在 JWTPayload 中放置 敏感信息

2.3. Signature

要创建签名部分,需要利用 秘钥Base64 编码后的 HeaderPayload 进行 加密,加密算法的公式如下:

HMACSHA256(
    base64UrlEncode(header) + '.' +
    base64UrlEncode(payload),
    secret
)

签名 可以用于验证 消息传递过程 中有没有被更改。对于使用 私钥签名token,它还可以验证 JWT发送方 是否为它所称的 发送方

3. JWT的工作方式

客户端 获取 JWT 后,对于以后的 每次请求,都不需要再通过 授权服务 来判断该请求的 用户 以及该 用户的权限。在微服务系统中,可以利用 JWT 实现 单点登录。认证流程图如下:

4. 案例工程结构

  • eureka-server:作为 注册服务中心,端口号为 8761。这里不再演示搭建。

  • auth-service:作为 授权服务授权 需要用户提供 客户端client IdClient Secret,以及 授权用户usernamepassword。这些信息 准备无误 之后,auth-service 会返回 JWT,该 JWT 包含了用户的 基本信息权限点信息,并通过 RSA 私钥 进行加密。

  • user-service:作为 资源服务,它的 资源 被保护起来,需要相应的 权限 才能访问。user-service 服务得到 用户请求JWT 后,先通过 公钥 解密 JWT,得到 JWT 对应的 用户信息用户权限信息,再通过 Spring Security 判断该用户是否有 权限 访问该资源。

工程原理示意图如下:

5. 构建auth-service授权服务

  • 新建一个 auth-service 项目模块,完整的 pom.xml 文件配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>auth-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>auth-service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--防止jks文件被mavne编译导致不可用-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <nonFilteredFileExtensions>
                        
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值