升级Spring Cloud Hoxton & Alibaba,认证授权改用Oauth2。
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package com.macro.mall.authorization;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.macro.mall.common.constant.AuthConstant;
|
||||
import com.macro.mall.common.domain.UserDto;
|
||||
import com.macro.mall.config.IgnoreUrlsConfig;
|
||||
import com.nimbusds.jose.JWSObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
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.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 鉴权管理器,用于判断是否有资源的访问权限
|
||||
* Created by macro on 2020/6/19.
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private IgnoreUrlsConfig ignoreUrlsConfig;
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
|
||||
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
|
||||
URI uri = request.getURI();
|
||||
PathMatcher pathMatcher = new AntPathMatcher();
|
||||
//白名单路径直接放行
|
||||
List<String> ignoreUrls = ignoreUrlsConfig.getUrls();
|
||||
for (String ignoreUrl : ignoreUrls) {
|
||||
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
||||
return Mono.just(new AuthorizationDecision(true));
|
||||
}
|
||||
}
|
||||
//对应跨域的预检请求直接放行
|
||||
if(request.getMethod()==HttpMethod.OPTIONS){
|
||||
return Mono.just(new AuthorizationDecision(true));
|
||||
}
|
||||
//不同用户体系登录不允许互相访问
|
||||
try {
|
||||
String token = request.getHeaders().getFirst(AuthConstant.JWT_TOKEN_HEADER);
|
||||
if(StrUtil.isEmpty(token)){
|
||||
return Mono.just(new AuthorizationDecision(false));
|
||||
}
|
||||
String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, "");
|
||||
JWSObject jwsObject = JWSObject.parse(realToken);
|
||||
String userStr = jwsObject.getPayload().toString();
|
||||
UserDto userDto = JSONUtil.toBean(userStr, UserDto.class);
|
||||
if (AuthConstant.ADMIN_CLIENT_ID.equals(userDto.getClientId()) && !pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
|
||||
return Mono.just(new AuthorizationDecision(false));
|
||||
}
|
||||
if (AuthConstant.PORTAL_CLIENT_ID.equals(userDto.getClientId()) && pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
|
||||
return Mono.just(new AuthorizationDecision(false));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
return Mono.just(new AuthorizationDecision(false));
|
||||
}
|
||||
//非管理端路径直接放行
|
||||
if (!pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
|
||||
return Mono.just(new AuthorizationDecision(true));
|
||||
}
|
||||
//管理端路径需校验权限
|
||||
Map<Object, Object> resourceRolesMap = redisTemplate.opsForHash().entries(AuthConstant.RESOURCE_ROLES_MAP_KEY);
|
||||
Iterator<Object> iterator = resourceRolesMap.keySet().iterator();
|
||||
List<String> authorities = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
String pattern = (String) iterator.next();
|
||||
if (pathMatcher.match(pattern, uri.getPath())) {
|
||||
authorities.addAll(Convert.toList(String.class, resourceRolesMap.get(pattern)));
|
||||
}
|
||||
}
|
||||
authorities = authorities.stream().map(i -> i = AuthConstant.AUTHORITY_PREFIX + i).collect(Collectors.toList());
|
||||
//认证通过且角色匹配的用户可访问当前路径
|
||||
return mono
|
||||
.filter(Authentication::isAuthenticated)
|
||||
.flatMapIterable(Authentication::getAuthorities)
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.any(authorities::contains)
|
||||
.map(AuthorizationDecision::new)
|
||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.macro.mall.component;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.macro.mall.common.api.CommonResult;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 自定义返回结果:没有登录或token过期时
|
||||
* Created by macro on 2020/6/18.
|
||||
*/
|
||||
@Component
|
||||
public class RestAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
|
||||
@Override
|
||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
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(CommonResult.unauthorized(e.getMessage()));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.macro.mall.component;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.macro.mall.common.api.CommonResult;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
/**
|
||||
* 自定义返回结果:没有权限访问时
|
||||
* Created by macro on 2018/4/26.
|
||||
*/
|
||||
@Component
|
||||
public class RestfulAccessDeniedHandler implements ServerAccessDeniedHandler {
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
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(CommonResult.forbidden(denied.getMessage()));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public class GlobalCorsConfig {
|
||||
config.addAllowedMethod("*");
|
||||
config.addAllowedOrigin("*");
|
||||
config.addAllowedHeader("*");
|
||||
|
||||
config.setAllowCredentials(true);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.macro.mall.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网关白名单配置
|
||||
* Created by macro on 2020/6/17.
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="secure.ignore")
|
||||
public class IgnoreUrlsConfig {
|
||||
private List<String> urls;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.macro.mall.config;
|
||||
|
||||
import com.macro.mall.common.config.BaseRedisConfig;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis相关配置
|
||||
* Created by macro on 2020/6/19.
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig extends BaseRedisConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.macro.mall.config;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import com.macro.mall.authorization.AuthorizationManager;
|
||||
import com.macro.mall.common.constant.AuthConstant;
|
||||
import com.macro.mall.component.RestAuthenticationEntryPoint;
|
||||
import com.macro.mall.component.RestfulAccessDeniedHandler;
|
||||
import com.macro.mall.filter.IgnoreUrlsRemoveJwtFilter;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
|
||||
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 reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 资源服务器配置
|
||||
* Created by macro on 2020/6/19.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
public class ResourceServerConfig {
|
||||
private final AuthorizationManager authorizationManager;
|
||||
private final IgnoreUrlsConfig ignoreUrlsConfig;
|
||||
private final RestfulAccessDeniedHandler restfulAccessDeniedHandler;
|
||||
private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
|
||||
private final IgnoreUrlsRemoveJwtFilter ignoreUrlsRemoveJwtFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
||||
http.oauth2ResourceServer().jwt()
|
||||
.jwtAuthenticationConverter(jwtAuthenticationConverter());
|
||||
//自定义处理JWT请求头过期或签名错误的结果
|
||||
http.oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint);
|
||||
//对白名单路径,直接移除JWT请求头
|
||||
http.addFilterBefore(ignoreUrlsRemoveJwtFilter,SecurityWebFiltersOrder.AUTHENTICATION);
|
||||
http.authorizeExchange()
|
||||
.pathMatchers(ArrayUtil.toArray(ignoreUrlsConfig.getUrls(),String.class)).permitAll()//白名单配置
|
||||
.anyExchange().access(authorizationManager)//鉴权管理器配置
|
||||
.and().exceptionHandling()
|
||||
.accessDeniedHandler(restfulAccessDeniedHandler)//处理未授权
|
||||
.authenticationEntryPoint(restAuthenticationEntryPoint)//处理未认证
|
||||
.and().csrf().disable();
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX);
|
||||
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME);
|
||||
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
|
||||
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.macro.mall.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;
|
||||
|
||||
/**
|
||||
* Swagger资源配置
|
||||
* Created by macro on 2020/7/9.
|
||||
*/
|
||||
@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<>();
|
||||
//获取所有路由的ID
|
||||
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
|
||||
//过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.macro.mall.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.macro.mall.common.constant.AuthConstant;
|
||||
import com.nimbusds.jose.JWSObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* 将登录用户的JWT转化成用户信息的全局过滤器
|
||||
* Created by macro on 2020/6/17.
|
||||
*/
|
||||
@Component
|
||||
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(AuthGlobalFilter.class);
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
String token = exchange.getRequest().getHeaders().getFirst(AuthConstant.JWT_TOKEN_HEADER);
|
||||
if (StrUtil.isEmpty(token)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
try {
|
||||
//从token中解析用户信息并设置到Header中去
|
||||
String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, "");
|
||||
JWSObject jwsObject = JWSObject.parse(realToken);
|
||||
String userStr = jwsObject.getPayload().toString();
|
||||
LOGGER.info("AuthGlobalFilter.filter() user:{}",userStr);
|
||||
ServerHttpRequest request = exchange.getRequest().mutate().header(AuthConstant.USER_TOKEN_HEADER, userStr).build();
|
||||
exchange = exchange.mutate().request(request).build();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.macro.mall.filter;
|
||||
|
||||
import com.macro.mall.common.constant.AuthConstant;
|
||||
import com.macro.mall.config.IgnoreUrlsConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 白名单路径访问时需要移除JWT请求头
|
||||
* Created by macro on 2020/7/24.
|
||||
*/
|
||||
@Component
|
||||
public class IgnoreUrlsRemoveJwtFilter implements WebFilter {
|
||||
@Autowired
|
||||
private IgnoreUrlsConfig ignoreUrlsConfig;
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
URI uri = request.getURI();
|
||||
PathMatcher pathMatcher = new AntPathMatcher();
|
||||
//白名单路径移除JWT请求头
|
||||
List<String> ignoreUrls = ignoreUrlsConfig.getUrls();
|
||||
for (String ignoreUrl : ignoreUrls) {
|
||||
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
||||
request = exchange.getRequest().mutate().header(AuthConstant.JWT_TOKEN_HEADER, "").build();
|
||||
exchange = exchange.mutate().request(request).build();
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.macro.mall.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;
|
||||
|
||||
/**
|
||||
* 自定义Swagger的各个配置节点
|
||||
* Created by macro on 2020/7/9.
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swagger安全配置,支持oauth和apiKey设置
|
||||
*/
|
||||
@GetMapping("/swagger-resources/configuration/security")
|
||||
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
|
||||
return Mono.just(new ResponseEntity<>(
|
||||
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swagger UI配置
|
||||
*/
|
||||
@GetMapping("/swagger-resources/configuration/ui")
|
||||
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
|
||||
return Mono.just(new ResponseEntity<>(
|
||||
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swagger资源配置,微服务中这各个服务的api-docs信息
|
||||
*/
|
||||
@GetMapping("/swagger-resources")
|
||||
public Mono<ResponseEntity> swaggerResources() {
|
||||
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
eureka:
|
||||
client:
|
||||
service-url:
|
||||
defaultZone: http://localhost:8001/eureka/
|
||||
registry-fetch-interval-seconds: 10
|
||||
@@ -1,7 +0,0 @@
|
||||
eureka:
|
||||
client:
|
||||
service-url:
|
||||
defaultZone: http://mall-registry:8001/eureka/
|
||||
registry-fetch-interval-seconds: 10
|
||||
instance:
|
||||
prefer-ip-address: true
|
||||
@@ -1,16 +1,77 @@
|
||||
server:
|
||||
port: 8201
|
||||
spring:
|
||||
application:
|
||||
name: mall-gateway
|
||||
profiles:
|
||||
active: dev
|
||||
cloud:
|
||||
gateway:
|
||||
discovery:
|
||||
locator:
|
||||
enabled: true
|
||||
lower-case-service-id: true #使用小写service-id
|
||||
routes: #配置路由路径
|
||||
- id: mall-auth
|
||||
uri: lb://mall-auth
|
||||
predicates:
|
||||
- Path=/mall-auth/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
- id: mall-admin
|
||||
uri: lb://mall-admin
|
||||
predicates:
|
||||
- Path=/mall-admin/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
- id: mall-portal
|
||||
uri: lb://mall-portal
|
||||
predicates:
|
||||
- Path=/mall-portal/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
- id: mall-search
|
||||
uri: lb://mall-search
|
||||
predicates:
|
||||
- Path=/mall-search/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
- id: mall-demo
|
||||
uri: lb://mall-demo
|
||||
predicates:
|
||||
- Path=/mall-demo/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: 'http://localhost:8201/mall-auth/rsa/publicKey' #配置RSA的公钥访问地址
|
||||
redis:
|
||||
database: 0
|
||||
port: 6379
|
||||
host: localhost
|
||||
password:
|
||||
secure:
|
||||
ignore:
|
||||
urls: #配置白名单路径
|
||||
- "/doc.html"
|
||||
- "/swagger-resources/**"
|
||||
- "/swagger/**"
|
||||
- "/**/v2/api-docs"
|
||||
- "/**/*.js"
|
||||
- "/**/*.css"
|
||||
- "/**/*.png"
|
||||
- "/**/*.ico"
|
||||
- "/webjars/springfox-swagger-ui/**"
|
||||
- "/actuator/**"
|
||||
- "/mall-auth/oauth/token"
|
||||
- "/mall-auth/rsa/publicKey"
|
||||
- "/mall-search/**"
|
||||
- "/mall-portal/sso/**"
|
||||
- "/mall-portal/home/**"
|
||||
- "/mall-portal/product/**"
|
||||
- "/mall-portal/brand/**"
|
||||
- "/mall-admin/admin/login"
|
||||
- "/mall-admin/admin/register"
|
||||
- "/mall-admin/admin/info"
|
||||
- "/mall-admin/minio/upload"
|
||||
management: #开启SpringBoot Admin的监控
|
||||
endpoints:
|
||||
web:
|
||||
@@ -19,6 +80,3 @@ management: #开启SpringBoot Admin的监控
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
logging:
|
||||
level:
|
||||
org.springframework.cloud.gateway: debug
|
||||
|
||||
8
mall-gateway/src/main/resources/bootstrap-dev.yml
Normal file
8
mall-gateway/src/main/resources/bootstrap-dev.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: http://localhost:8848
|
||||
config:
|
||||
server-addr: http://localhost:8848
|
||||
file-extension: yaml
|
||||
8
mall-gateway/src/main/resources/bootstrap-prod.yml
Normal file
8
mall-gateway/src/main/resources/bootstrap-prod.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: http://nacos-registry:8848
|
||||
config:
|
||||
server-addr: http://nacos-registry:8848
|
||||
file-extension: yaml
|
||||
5
mall-gateway/src/main/resources/bootstrap.yml
Normal file
5
mall-gateway/src/main/resources/bootstrap.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: mall-gateway
|
||||
Reference in New Issue
Block a user