1. 概述
在微服务开发过程中,通常都会使用Spring Cloud Gateway构建统一的API网关,在访问微服务之前都会先校验访问者是否有权限访问资源,实现方式有很多,这里主要介绍Spring Cloud Gateway集成OAuth2.1如何实现网关统一认证。
Spring Cloud Gateway在认证过程中既可以作为OAuth Client,也可以作为OAuth Resource Server
作为OAuth Client流程如下:
作为OAuth Resource Server流程如下:
本文主要以基于OAuth Client实现,会涉及到三个微服务,一个认证中心服务,一个网关Client服务,一个后台资源服务
2. 搭建认证中心
认证中心的搭建可以参考SpringBoot3集成Spring Authorization Server搭建服务认证中心,不同的是在application.yml中配置如下属性:
server:
port: 9000
spring:
security:
oauth2:
authorizationserver:
client:
client-server-oidc:
registration:
client-id: client-server
client-secret: '{noop}secret'
client-authentication-methods:
- client_secret_basic
authorization-grant-types:
- authorization_code
- refresh_token
- client_credentials
redirect-uris:
- http://127.0.0.1:8010/login/oauth2/code/client-server-oidc
scopes:
- openid
- profile
client-name: client-server
require-authorization-consent: true
3. 搭建后台资源服务
3.1. 引入核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
3.2. 编写application.yml
server:
port: 8000
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://127.0.0.1:9000
3.3. 编写ResourceServerConfig
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(jsr250Enabled = true, securedEnabled = true)
public class ResourceServerConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
.oauth2ResourceServer((oauth2Resource) -> oauth2Resource.jwt(Customizer.withDefaults()));
return http.build();
}
}
3.4. 编写ResourceController
编写一个接口用于网关调用
@RestController
public class ResourceController {
@GetMapping(value = "/resources")
public String[] getResources() {
return new String[] {"Resource 1", "Resource 2", "Resource 3"};
}
}
4. 搭建Gateway Client
4.1. 引入核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
4.2. 编写application.yml
server:
port: 8010
spring:
cloud:
gateway:
default-filters:
- TokenRelay=
routes:
- id: backend_resource_route
uri: http://127.0.0.1:8000
predicates:
- Path=/resources/**
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://127.0.0.1:9000
client:
provider:
oauth-server:
issuer-uri: http://127.0.0.1:9000
user-info-uri: ${spring.security.oauth2.client.provider.oauth-server.issuer-uri}/user
authorization-uri: ${spring.security.oauth2.client.provider.oauth-server.issuer-uri}/oauth2/authorize
token-uri: ${spring.security.oauth2.client.provider.oauth-server.issuer-uri}/oauth2/token
registration:
client-server-oidc:
provider: oauth-server
client-id: client-server
client-secret: secret
client-name: client-server-oidc
authorization-grant-type: authorization_code
redirect-uri: http://127.0.0.1:8010/login/oauth2/code/{registrationId}
scope:
- profile
- openid
4.3. 编写WebSecurityConfig
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig {
@Bean
SecurityWebFilterChain defaultSecurityWebFilterChain(ServerHttpSecurity http) {
http.authorizeExchange((authorize) -> authorize.anyExchange().authenticated());
http.oauth2Login(Customizer.withDefaults());
http.oauth2ResourceServer((oauth2Resource) -> oauth2Resource.jwt(Customizer.withDefaults()));
http.csrf((csrf) -> csrf.disable());
http.cors((cors) -> cors.disable());
return http.build();
}
}
5. 测试验证
依次启动认证中心服务,后台资源服务和网关Client服务,在浏览器输入http://127.0.0.1:8010/resources,会进入登录页面,输入用户名和密码admin/123456,授权服务后,页面会返回后台资源服务接口返回的数据