初始化

This commit is contained in:
2022-06-21 20:47:46 +08:00
parent b666a24a98
commit 59da3376c1
1246 changed files with 129600 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package com.njcn.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年05月10日 14:03
*/
@EnableFeignClients
@SpringBootApplication
public class GatewayMain {
public static void main(String[] args) {
SpringApplication.run(GatewayMain.class,args);
}
}

View File

@@ -0,0 +1,120 @@
package com.njcn.gateway.config;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.gateway.enums.GateWayEnum;
import com.njcn.gateway.security.AuthorizationManager;
import com.njcn.gateway.utils.ResponseUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
import reactor.core.publisher.Mono;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
/**
* @author hongawen
* 资源服务器配置
*/
@AllArgsConstructor
@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfig {
private final AuthorizationManager authorizationManager;
private final WhiteListConfig whiteListConfig;
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter())
// 本地获取公钥
.publicKey(rsaPublicKey());
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
http.oauth2ResourceServer().authenticationEntryPoint(authenticationEntryPoint());
http.authorizeExchange()
.pathMatchers(Convert.toStrArray(whiteListConfig.getUrls())).permitAll()
.anyExchange().access(authorizationManager)
.and()
.exceptionHandling()
// 处理未授权
.accessDeniedHandler(accessDeniedHandler())
// 处理未认证
.authenticationEntryPoint(authenticationEntryPoint())
.and().csrf().disable();
return http.build();
}
/**
* 访问拒绝处理器
*/
@Bean
ServerAccessDeniedHandler accessDeniedHandler() {
return (exchange, denied) -> Mono.defer(() -> Mono.just(exchange.getResponse()))
.flatMap(response -> ResponseUtils.writeErrorInfo(response, GateWayEnum.NO_AUTHORIZATION));
}
/**
* token无效或者已过期自定义响应
*/
@Bean
ServerAuthenticationEntryPoint authenticationEntryPoint() {
return (exchange, e) -> Mono.defer(() -> Mono.just(exchange.getResponse()))
.flatMap(response -> ResponseUtils.writeErrorInfo(response, GateWayEnum.ACCESS_TOKEN_EXPIRE_JWT));
}
/**
* @link https://blog.csdn.net/qq_24230139/article/details/105091273
* ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
* 需要把jwt的Claim中的authorities加入
* 方案重新定义权限管理器默认转换器JwtGrantedAuthoritiesConverter
*/
@Bean
public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthorityPrefix(SecurityConstants.AUTHORITY_PREFIX);
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(SecurityConstants.JWT_AUTHORITIES_KEY);
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
}
/**
* 本地获取JWT验签公钥
*/
@SneakyThrows
@Bean
public RSAPublicKey rsaPublicKey() {
Resource resource = new ClassPathResource("public.key");
InputStream is = resource.getInputStream();
String publicKeyData = IoUtil.read(is).toString();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec((Base64.decode(publicKeyData)));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
}

View File

@@ -0,0 +1,55 @@
package com.njcn.gateway.config;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.List;
/**
* @author hongawen
*/
@Slf4j
@Component
@Primary
@AllArgsConstructor
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
route.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("**", "v2/api-docs"))));
});
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
log.info("name:{},location:{}",name,location);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}

View File

@@ -0,0 +1,22 @@
package com.njcn.gateway.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* 网关白名单配置
* @author hongawen
* @version 1.0.0
* @date 2021年05月11日 10:33
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "whitelist")
public class WhiteListConfig {
private List<String> urls;
}

View File

@@ -0,0 +1,35 @@
package com.njcn.gateway.enums;
import lombok.Getter;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年06月04日 11:17
*/
@Getter
public enum GateWayEnum {
/**
* A0200 ~ A0249 作用于网关业务枚举
* 网关业务枚举响应
*/
NO_AUTHORIZATION("A0201", "访问未授权"),
//特殊的code与common中的code保持一致
TOKEN_EXPIRE_JWT("A0024", "token已过期"),
ACCESS_TOKEN_EXPIRE_JWT("A0202", "access_token已过期"),
TOKEN_FORBIDDEN_JWT("A0203", "token已被禁止访问");
private final String code;
private final String message;
GateWayEnum(String code, String message) {
this.code = code;
this.message = message;
}
}

View File

@@ -0,0 +1,99 @@
package com.njcn.gateway.filter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.nimbusds.jose.JWSObject;
import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.common.pojo.dto.UserTokenInfo;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gateway.enums.GateWayEnum;
import com.njcn.gateway.utils.IpUtils;
import com.njcn.gateway.utils.ResponseUtils;
import com.njcn.redis.utils.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
/**
* 全局过滤器
*
* @author hongawen
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {
private final static List<String> USER_AGENT_IP = Arrays.asList("/pqs-auth/auth/getImgCode", "/pqs-auth/oauth/token", "/user-boot/user/generateSm2Key", "/user-boot/user/updateFirstPassword");
private final RedisUtil redisUtil;
@SneakyThrows
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String realIp = IpUtils.getRealIpAddress(request);
// 非JWT或者JWT为空不作处理
String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_KEY);
String path = request.getURI().getPath();
if (StrUtil.isBlank(token) || !token.startsWith(SecurityConstants.AUTHORIZATION_PREFIX)) {
// String path = request.getURI().getPath();
//未认证且这些请求需要
if (USER_AGENT_IP.contains(path)) {
request = exchange.getRequest().mutate()
.header(SecurityConstants.REQUEST_HEADER_KEY_CLIENT_REAL_IP, realIp)
.build();
return chain.filter(exchange.mutate().request(request).build());
}
return chain.filter(exchange);
}
// 解析JWT获取jti以jti为key判断redis的黑名单列表是否存在存在拦截响应token失效
token = token.replace(SecurityConstants.AUTHORIZATION_PREFIX, Strings.EMPTY);
JWSObject jwsObject = JWSObject.parse(token);
String payload = jwsObject.getPayload().toString();
JSONObject jsonObject = JSONUtil.parseObj(payload);
String userIndex = jsonObject.getStr(SecurityConstants.USER_INDEX_KEY);
String jti = jsonObject.getStr(SecurityConstants.JWT_JTI);
String blackUserKey = SecurityConstants.TOKEN_BLACKLIST_PREFIX + userIndex;
List<UserTokenInfo> blackUsers = (List<UserTokenInfo>) redisUtil.getObjectByKey(blackUserKey);
if (CollectionUtils.isNotEmpty(blackUsers)) {
for (UserTokenInfo blackUser : blackUsers) {
//存在当前的刷新token则抛出业务异常
if(blackUser.getAccessTokenJti().equalsIgnoreCase(jti)){
return ResponseUtils.writeErrorInfo(response, GateWayEnum.TOKEN_EXPIRE_JWT);
}
}
}
// 存在token且不是黑名单request写入JWT的载体信息
request = exchange.getRequest().mutate()
.header(SecurityConstants.JWT_PAYLOAD_KEY, URLEncoder.encode(payload, StandardCharsets.UTF_8.toString()))
.header(SecurityConstants.REQUEST_HEADER_KEY_CLIENT_REAL_IP, realIp)
.build();
exchange = exchange.mutate().request(request).build();
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}

View File

@@ -0,0 +1,36 @@
package com.njcn.gateway.filter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年05月11日 10:33
*/
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
private static final String HEADER_NAME = "X-Forwarded-Prefix";
private static final String URI = "/v2/api-docs";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path, URI)) {
return chain.filter(exchange);
}
String basePath = path.substring(0, path.lastIndexOf(URI));
ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}

View File

@@ -0,0 +1,52 @@
package com.njcn.gateway.handler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;
import java.util.Optional;
/**
* * @author hongawen
* * @version 1.0.0
* * @createTime 2021年05月10日 14:03
*/
@RestController
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/swagger-resources/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}

View File

@@ -0,0 +1,82 @@
package com.njcn.gateway.security;
import cn.hutool.core.collection.CollectionUtil;
import com.njcn.redis.pojo.enums.RedisKeyEnum;
import com.njcn.redis.utils.RedisUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import reactor.core.publisher.Mono;
import java.util.*;
/**
* @author hongawen
* 鉴权管理器
*/
@Slf4j
@Component
@AllArgsConstructor
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
private final RedisUtil redisUtil;
@Override
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
PathMatcher pathMatcher = new AntPathMatcher();
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
//不追究请求方式如果需追求需要在数据库中添加请求方式的字段request.getMethodValue()
String restPath = request.getURI().getPath();
log.info("请求路径:{}", restPath);
// 对应跨域的预检请求直接放行
// if (request.getMethod() == HttpMethod.OPTIONS) {
// return Mono.just(new AuthorizationDecision(true));
// }
// 是否需要鉴权,默认未设置拦截规则需要鉴权
boolean requireCheck = true;
//查看是否为公共资源
List<String> publicFunctions = (List<String>) redisUtil.getObjectByKey(RedisKeyEnum.PUBLIC_FUNCTIONS_KEY.getKey());
if (CollectionUtil.isNotEmpty(publicFunctions) && publicFunctions.contains(restPath)) {
requireCheck = false;
}
// 从缓存取资源权限角色关系列表
Object roleFunctionsObject = redisUtil.getObjectByKey(RedisKeyEnum.ROLE_FUNCTION_KEY.getKey());
if (!Objects.isNull(roleFunctionsObject)) {
Map<String, List<String>> roleFunctions = (Map<String, List<String>>) roleFunctionsObject;
//当前资源需要的角色
Set<String> authorities = new HashSet<>();
Set<String> roleNames = roleFunctions.keySet();
roleNames.forEach(roleName -> {
List<String> functionPaths = roleFunctions.get(roleName);
if (CollectionUtil.isNotEmpty(functionPaths) && functionPaths.contains(restPath)) {
authorities.add(roleName);
}
});
boolean finalRequireCheck = requireCheck;
return mono
.filter(Authentication::isAuthenticated)
.flatMapIterable(Authentication::getAuthorities)
.map(GrantedAuthority::getAuthority)
.any(roleId -> {
if (!finalRequireCheck || roleId.equals("ROLE_root")) {
return true;
} else {
return authorities.contains(roleId);
}
})
.map(AuthorizationDecision::new)
.defaultIfEmpty(new AuthorizationDecision(false));
}
return Mono.just(new AuthorizationDecision(true));
}
}

View File

@@ -0,0 +1,20 @@
package com.njcn.gateway.utils;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.gateway.enums.GateWayEnum;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年06月04日 11:22
*/
public class GatePubUtils {
/**
* 通用结果集
*/
public static <T> HttpResult<T> assembleGateWayResponseResult(GateWayEnum responseEnum, T result, String methodDescribe) {
return HttpResultUtil.assembleResult(responseEnum.getCode(), result, methodDescribe + responseEnum.getMessage());
}
}

View File

@@ -0,0 +1,86 @@
package com.njcn.gateway.utils;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年05月25日 11:25
*/
@Slf4j
public class IpUtils {
private static final String UNKNOWN = "unknown";
private static final String LOCALHOST_IPV4 = "127.0.0.1";
private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
private static final String SEPARATOR = ",";
private static final String HEADER_X_FORWARDED_FOR = "x-forwarded-for";
private static final String HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP";
private static final String HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
private static final int IP_LEN = 15;
/**
* 获取用户真实IP地址不直接使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
* <p>
* 可是如果通过了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP值究竟哪个才是真正的用户端的真实IP呢
* 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
* <p>
* 如X-Forwarded-For192.168.1.110, 192.168.1.120, 192.168.1.130,
* 192.168.1.100
* <p>
* 用户真实IP为 192.168.1.110
*/
public static String getRealIpAddress(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
String ipAddress = headers.getFirst(HEADER_X_FORWARDED_FOR);
if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = headers.getFirst(HEADER_PROXY_CLIENT_IP);
}
if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = headers.getFirst(HEADER_WL_PROXY_CLIENT_IP);
}
if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = Optional.ofNullable(request.getRemoteAddress())
.map(address -> address.getAddress().getHostAddress())
.orElse("");
if (LOCALHOST_IPV4.equals(ipAddress) || LOCALHOST_IPV6.equals(ipAddress)) {
// 根据网卡取本机配置的IP
try {
InetAddress inet = InetAddress.getLocalHost();
ipAddress = inet.getHostAddress();
} catch (UnknownHostException e) {
log.error("解析请求IP失败,{}", Stream.of(e.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining(StrUtil.CRLF)));
}
}
}
// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > IP_LEN) {
int index = ipAddress.indexOf(SEPARATOR);
if (index > 0) {
ipAddress = ipAddress.substring(0, index);
}
}
return ipAddress;
}
/**
* 获取客户端端口
*/
public static Integer getPort(ServerHttpRequest request) {
return request.getRemoteAddress().getPort();
}
}

View File

@@ -0,0 +1,51 @@
package com.njcn.gateway.utils;
import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.gateway.enums.GateWayEnum;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
/**
* @author hongawen
* @version 1.0.0
* @date 2021年12月16日 10:26
*/
public class ResponseUtils {
public static Mono<Void> writeErrorInfo(ServerHttpResponse response, GateWayEnum gateWayEnum) {
// switch (gateWayEnum) {
// case NO_AUTHORIZATION:
// case PARSE_TOKEN_EXPIRE_JWT:
// response.setStatusCode(HttpStatus.OK);
// break;
// case PARSE_TOKEN_FORBIDDEN_JWT:
// response.setStatusCode(HttpStatus.FORBIDDEN);
// break;
// default:
// response.setStatusCode(HttpStatus.BAD_REQUEST);
// break;
// }
response.setStatusCode(HttpStatus.OK);
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
response.getHeaders().set("Access-Control-Allow-Origin", "*");
response.getHeaders().set("Cache-Control", "no-cache");
String body = JSONUtil.toJsonStr(
HttpResultUtil.assembleResult(gateWayEnum.getCode(), null, StringUtil.EMPTY + gateWayEnum.getMessage())
);
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer))
.doOnError(error -> DataBufferUtils.release(buffer));
}
}

View File

@@ -0,0 +1,138 @@
#当前服务的基本信息
microservice:
ename: @artifactId@
name: "@name@"
version: @version@
sentinel:
url: @sentinel.url@
gateway:
url: @gateway.url@
server:
port: 10215
spring:
application:
name: @artifactId@
main:
allow-bean-definition-overriding: true
#nacos注册中心以及配置中心的指定
cloud:
nacos:
discovery:
server-addr: @nacos.url@
namespace: @nacos.namespace@
config:
server-addr: @nacos.url@
namespace: @nacos.namespace@
file-extension: yaml
shared-configs:
- data-id: share-config.yaml
refresh: true
- data-Id: share-config-datasource-db.yaml
refresh: true
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowCredentials: true
exposedHeaders: "Content-Disposition,Content-Type,Cache-Control"
allowedHeaders: "*"
allowedOrigins: "*"
allowedMethods: "*"
discovery:
locator:
# 开启自动代理 (自动装载从配置中心serviceId)
enabled: true
# 服务id为true --> 这样小写服务就可访问了
lower-case-service-id: true
routes:
- id: pqs-auth
uri: lb://pqs-auth
predicates:
- Path=/pqs-auth/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: user-boot
uri: lb://user-boot
predicates:
- Path=/user-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: device-boot
uri: lb://device-boot
predicates:
- Path=/device-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: system-boot
uri: lb://system-boot
predicates:
- Path=/system-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: harmonic-boot
uri: lb://harmonic-boot
predicates:
- Path=/harmonic-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: energy-boot
uri: lb://energy-boot
predicates:
- Path=/energy-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
- id: event-boot
uri: lb://event-boot
predicates:
- Path=/event-boot/**
filters:
- SwaggerHeaderFilter
- StripPrefix=1
#项目日志的配置
logging:
config: http://@nacos.url@/nacos/v1/cs/configs?tenant=@nacos.namespace@&group=DEFAULT_GROUP&dataId=logback.xml
level:
root: info
whitelist:
urls:
- /
- /user-boot/user/generateSm2Key
- /user-boot/theme/getTheme
- /user-boot/user/updateFirstPassword
- /pqs-auth/oauth/logout
- /pqs-auth/oauth/token
- /pqs-auth/auth/getImgCode
- /pqs-auth/oauth/getPublicKey
- /pqs-auth/judgeToken/guangZhou
- /webjars/**
- /doc.html
- /swagger-resources/**
- /*/v2/api-docs
- /favicon.ico
- /device-boot/**
- /system-boot/**
- /harmonic-boot/**
- /energy-boot/**
- /event-boot/**

View File

@@ -0,0 +1,7 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn0GHes2u9gE0rAS3S0zM
20gJJdRr1yKPGs/yp7cTuz2wAYTsFdO2WKx+GS+DyHgBznJsbPS1KLpyAEJLRaGe
xz7T6GPK7yJExxU2eq0gmOLwFa9NS8gtsKpfpAc4C4J/Vc8S6X4vDEEQBdREM+lP
fmM4+694ev2+4hP0BbropMMrZXx49GxubmqGK1Ka2EUaHWrEG4Ik5ukQyYvNf8Ns
6KcaIUP7hHoha/z5cZkjFOOpXBGwx3AQvkuaMkhtOnrMBvLmmiP4TXErnJPXPz8s
xfeJXoz8T9aS+Dnvcpogqye2nam/CReLMikTXCPDDVyyT6sVNWVBfJZ/BPCR9gI1
3wIDAQAB