概述
Spring Cloud Gateway是一个构建在 Spring 生态之上的 API Gateway。 建立在Spring Boot 2.x、Spring WebFlux和Project Reactor之上。
本节中您将使用Spring Cloud Gateway将请求路由到Servlet API服务。
本文您将学到:
- OpenID Connect 身份验证 - 用于用户身份验证
- 令牌中继 - Spring Cloud Gateway API网关充当客户端将令牌转发到资源请求上
先决条件:
- Java 8+
- MySQL
- Redis
OpenID Connect身份验证
OpenID Connect 定义了一种基于 OAuth2 授权代码流的最终用户身份验证机制。下图是Spring Cloud Gateway与授权服务进行身份验证完整流程,为了清楚起见,其中一些参数已被省略。
创建授权服务
本节中我们将使用Spring Authorization Server 构建授权服务,支持OAuth2协议与OpenID Connect协议。同时我们还将使用RBAC0基本权限模型控制访问权限。并且该授权服务同时作为OAuth2客户端支持Github第三方登录。
相关数据库表结构
我们创建了基本RBAC0权限模型用于本文示例讲解,并提供了OAuth2授权服务持久化存储所需表结构和OAuth2客户端持久化存储所需表结构。通过oauth2_client_role定义外部系统角色与本平台角色映射关系。涉及相关创建表及初始化数据的SQL语句可以从这里获取。
角色说明
本节中授权服务默认提供两个角色,以下是角色属性及访问权限:
read | write | |
---|---|---|
ROLE_ADMIN | ✅ | ✅ |
ROLE_OPERATION | ✅ | ❎ |
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
配置
首先我们从application.yml配置开始,这里我们指定了端口号与MySQL连接配置:
server:
port: 8080
spring:
datasource:
druid:
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/oauth2server?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: <<username>> # 修改用户名
password: <<password>> # 修改密码
接下来我们将创建AuthorizationServerConfig
,用于配置OAuth2及OIDC所需Bean,首先我们将新增OAuth2客户端信息,并持久化到数据库:
@Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
RegisteredClient registeredClient = RegisteredClient.withId("relive-messaging-oidc")
.clientId("relive-client")
.clientSecret("{noop}relive-client")
.clientAuthenticationMethods(s -> {
s.add(ClientAuthenticationMethod.CLIENT_SECRET_POST);
s.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
})
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("http://127.0.0.1:8070/login/oauth2/code/messaging-gateway-oidc")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.scope(OidcScopes.EMAIL)
.scope("read")
.clientSettings(ClientSettings.builder()
.requireAuthorizationConsent(false) //不需要授权同意
.requireProofKey(false)
.build())
.tokenSettings(TokenSettings.builder()
.accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED) // 生成JWT令牌
.idTokenSignatureAlgorithm(SignatureAlgorithm.RS256)
.accessTokenTimeToLive(Duration.ofSeconds(30 * 60))//accessTokenTimeToLive:access_token有效期
.refreshTokenTimeToLive(Duration.ofSeconds(60 * 60))//refreshTokenTimeToLive:refresh_token有效期
.reuseRefreshTokens(true)
.build())
.build();
JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
registeredClientRepository.save(registeredClient);
return registeredClientRepository;
}
其次我们将创建授权过程中所需持久化容器