场景:
按职能,鉴权系统需要划分 网关(spring gateway) + 鉴权(auth-server)。本文通过实践搭建鉴权系统。
spring gateway
首先引入pom依赖
1、resilience 熔断器
2、gateway 网关
3、eureka client 服务注册中心
4、lombok插件
5、actuator状态监控
<dependencies>
<!-- 熔断器-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-feign</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
application.yml配置
1、gateway信息
2、actuator状态信息
3、配置eureka server地址及注册信息
4、日志配置
5、获取oauth2的jwt key
server:
port: 18890
spring:
application:
name: open-api-gateway
profiles:
active: local
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
default-filters:
- AddRequestParameter=gateway_type, member
- AddRequestHeader=gateway_type, member
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: http://127.0.0.1:22001/eureka
logging:
level:
com.dq.edu: debug
com:
netflix:
discovery: error
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: http://127.0.0.1:18889/auth-server/private/jwk_public_key
gateway 项目目录
核心内容:security配置、PermissionFilter鉴权过滤器
1、security配置
package com.digquant.openapigateway.config;
import com.digquant.openapigateway.entity.Response;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
@Slf4j
@Configuration
@AllArgsConstructor
@EnableWebFluxSecurity
public class SecurityConfig {
private final ReactiveJwtDecoder jwtDecoder;
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.cors().disable().csrf().disable();
http
.authorizeExchange()
.pathMatchers("/**").permitAll()
.pathMatchers("/**/public/**").permitAll()
.pathMatchers("/**/static/**").permitAll()
.pathMatchers("/*/oauth/**").permitAll()
.pathMatchers("/actuator/**").permitAll()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.anyExchange().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(serverAccessDeniedHandler())
.authenticationEntryPoint(serverAuthenticationEntryPoint())
.and()
.oauth2ResourceServer()
.jwt()
.jwtDecoder(jwtDecoder)
.and()
.bearerTokenConverter(new ServerBearerTokenAuthenticationConverter());
return http.build();
}
@Bean
public ServerAccessDeniedHandler serverAccessDeniedHandler() {
return (exchange, denied) -> {
log.debug("没有权限");
String errMsg = StringUtils.hasText(denied.getMessage()) ? denied.getMessage() : "没有权限";
Response result = new Response(1, errMsg);
return create(exchange, result);
};
}
@Bean
public ServerAuthenticationEntryPoint serverAuthenticationEntryPoint