mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 13:03:43 +08:00
docs:授权服务配置注释完善
This commit is contained in:
parent
e1d52acda7
commit
a1e53c3aba
@ -58,7 +58,6 @@
|
|||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- nacos 依赖-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
@ -68,22 +67,15 @@
|
|||||||
<groupId>com.alibaba.cloud</groupId>
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
<artifactId>spring-cloud-starter-oauth2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.nimbusds</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>nimbus-jose-jwt</artifactId>
|
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -16,13 +16,17 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.authorizeRequests()
|
http
|
||||||
.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
||||||
.and().authorizeRequests().antMatchers("/rsa/publicKey").permitAll()
|
.and()
|
||||||
.antMatchers("/v2/api-docs").permitAll()
|
.authorizeRequests().antMatchers("/rsa/publicKey").permitAll().anyRequest().authenticated()
|
||||||
.anyRequest().permitAll();
|
.and()
|
||||||
|
.csrf().disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果不配置SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
|
||||||
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||||
return super.authenticationManagerBean();
|
return super.authenticationManagerBean();
|
||||||
|
@ -55,8 +55,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 认证依赖 -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-config</artifactId>
|
<artifactId>spring-security-config</artifactId>
|
||||||
@ -69,10 +67,7 @@
|
|||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-oauth2-jose</artifactId>
|
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.nimbusds</groupId>
|
|
||||||
<artifactId>nimbus-jose-jwt</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package com.youlai.gateway.auth;
|
package com.youlai.gateway.component;
|
||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.nimbusds.jose.JWSObject;
|
import com.nimbusds.jose.JWSObject;
|
||||||
import com.youlai.admin.api.dto.UserDTO;
|
import com.youlai.admin.api.dto.UserDTO;
|
||||||
import com.youlai.common.core.constant.AuthConstants;
|
import com.youlai.common.core.constant.AuthConstants;
|
||||||
import com.youlai.gateway.config.WhiteUrlsConfig;
|
import com.youlai.gateway.config.WhiteListConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@ -29,7 +28,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鉴权管理器,用于判断是否有资源的访问权限
|
* 鉴权管理器
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
|
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
|
||||||
@ -38,21 +37,21 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
|
|||||||
private RedisTemplate redisTemplate;
|
private RedisTemplate redisTemplate;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WhiteUrlsConfig whiteUrlsConfig;
|
private WhiteListConfig whiteListConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
|
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
|
||||||
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
|
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
|
||||||
URI uri = request.getURI();
|
URI uri = request.getURI();
|
||||||
//白名单路径直接放行
|
// 白名单路径直接放行
|
||||||
PathMatcher pathMatcher = new AntPathMatcher();
|
PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
List<String> whiteUrls = whiteUrlsConfig.getUrls();
|
List<String> whiteUrls = whiteListConfig.getUrls();
|
||||||
for (String ignoreUrl : whiteUrls) {
|
for (String ignoreUrl : whiteUrls) {
|
||||||
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
||||||
return Mono.just(new AuthorizationDecision(true));
|
return Mono.just(new AuthorizationDecision(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//对应跨域的预检请求直接放行
|
// 对应跨域的预检请求直接放行
|
||||||
if (request.getMethod() == HttpMethod.OPTIONS) {
|
if (request.getMethod() == HttpMethod.OPTIONS) {
|
||||||
return Mono.just(new AuthorizationDecision(true));
|
return Mono.just(new AuthorizationDecision(true));
|
||||||
}
|
}
|
||||||
@ -97,7 +96,7 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
|
|||||||
.filter(Authentication::isAuthenticated)
|
.filter(Authentication::isAuthenticated)
|
||||||
.flatMapIterable(Authentication::getAuthorities)
|
.flatMapIterable(Authentication::getAuthorities)
|
||||||
.map(GrantedAuthority::getAuthority)
|
.map(GrantedAuthority::getAuthority)
|
||||||
.any(roleId -> authorities.contains(roleId)) // 判断用户角色中是否有访问资源权限的角色,一个就好
|
.any(roleId -> authorities.contains(roleId))
|
||||||
.map(AuthorizationDecision::new)
|
.map(AuthorizationDecision::new)
|
||||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||||
|
|
@ -17,10 +17,10 @@ import reactor.core.publisher.Mono;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 无权限访问自定义异常
|
* 无权访问自定义响应
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class AccessDeniedHandler implements ServerAccessDeniedHandler {
|
public class CustomServerAccessDeniedHandler implements ServerAccessDeniedHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException e) {
|
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException e) {
|
@ -20,7 +20,7 @@ import java.nio.charset.Charset;
|
|||||||
* 无效token自定义异常
|
* 无效token自定义异常
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class AuthExceptionEntryPoint implements ServerAuthenticationEntryPoint {
|
public class CustomServerAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
|
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
|
||||||
ServerHttpResponse response=exchange.getResponse();
|
ServerHttpResponse response=exchange.getResponse();
|
@ -22,7 +22,7 @@ public class CorsConfig {
|
|||||||
config.setAllowCredentials(true);
|
config.setAllowCredentials(true);
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
|
||||||
source.registerCorsConfiguration("/**", config);
|
source.registerCorsConfiguration("/**", config);
|
||||||
|
|
||||||
return new CorsWebFilter(source);
|
return new CorsWebFilter(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ package com.youlai.gateway.config;
|
|||||||
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import com.youlai.common.core.constant.AuthConstants;
|
import com.youlai.common.core.constant.AuthConstants;
|
||||||
import com.youlai.gateway.auth.AuthorizationManager;
|
import com.youlai.gateway.component.AuthorizationManager;
|
||||||
import com.youlai.gateway.component.AuthExceptionEntryPoint;
|
import com.youlai.gateway.component.CustomServerAuthenticationEntryPoint;
|
||||||
import com.youlai.gateway.component.AccessDeniedHandler;
|
import com.youlai.gateway.component.CustomServerAccessDeniedHandler;
|
||||||
import com.youlai.gateway.filter.WhiteUrlsRemoveJwtFilter;
|
import com.youlai.gateway.filter.WhiteListRemoveJwtFilter;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -31,37 +31,36 @@ import reactor.core.publisher.Mono;
|
|||||||
public class ResourceServerConfig {
|
public class ResourceServerConfig {
|
||||||
|
|
||||||
private AuthorizationManager authorizationManager;
|
private AuthorizationManager authorizationManager;
|
||||||
private AccessDeniedHandler accessDeniedHandler;
|
private CustomServerAccessDeniedHandler customServerAccessDeniedHandler;
|
||||||
private AuthExceptionEntryPoint authExceptionEntryPoint;
|
private CustomServerAuthenticationEntryPoint customServerAuthenticationEntryPoint;
|
||||||
private WhiteUrlsConfig whiteUrlsConfig;
|
private WhiteListConfig whiteListConfig;
|
||||||
private WhiteUrlsRemoveJwtFilter whiteUrlsRemoveJwtFilter;
|
private WhiteListRemoveJwtFilter whiteListRemoveJwtFilter;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||||
http.oauth2ResourceServer().jwt()
|
http.oauth2ResourceServer().jwt()
|
||||||
.jwtAuthenticationConverter(jwtAuthenticationConverter());
|
.jwtAuthenticationConverter(jwtAuthenticationConverter());
|
||||||
// 自定义处理JWT请求头过期或签名错误的结果
|
// 自定义处理JWT请求头过期或签名错误的结果
|
||||||
http.oauth2ResourceServer().authenticationEntryPoint(authExceptionEntryPoint);
|
http.oauth2ResourceServer().authenticationEntryPoint(customServerAuthenticationEntryPoint);
|
||||||
// 对白名单路径,直接移除JWT请求头
|
// 对白名单路径,直接移除JWT请求头
|
||||||
http.addFilterBefore(whiteUrlsRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION);
|
http.addFilterBefore(whiteListRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION);
|
||||||
http.authorizeExchange()
|
http.authorizeExchange()
|
||||||
.pathMatchers(ArrayUtil.toArray(whiteUrlsConfig.getUrls(),String.class)).permitAll()
|
.pathMatchers(ArrayUtil.toArray(whiteListConfig.getUrls(),String.class)).permitAll()
|
||||||
.anyExchange().access(authorizationManager)
|
.anyExchange().access(authorizationManager)
|
||||||
.and()
|
.and()
|
||||||
.exceptionHandling()
|
.exceptionHandling()
|
||||||
.accessDeniedHandler(accessDeniedHandler) // 处理未授权
|
.accessDeniedHandler(customServerAccessDeniedHandler) // 处理未授权
|
||||||
.authenticationEntryPoint(authExceptionEntryPoint) //处理未认证
|
.authenticationEntryPoint(customServerAuthenticationEntryPoint) //处理未认证
|
||||||
.and().csrf().disable();
|
.and().csrf().disable();
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://blog.csdn.net/qq_24230139/article/details/105091273
|
* @linkhttps://blog.csdn.net/qq_24230139/article/details/105091273
|
||||||
* ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
|
* ServerHttpSecurity没有将jwt中authorities的负载部分当做Authentication
|
||||||
* 需要把jwt的Claim中的authorities加入
|
* 需要把jwt的Claim中的authorities加入
|
||||||
* 方案:重新定义ReactiveAuthenticationManager权限管理器,默认转换器JwtGrantedAuthoritiesConverter
|
* 方案:重新定义ReactiveAuthenticationManager权限管理器,默认转换器JwtGrantedAuthoritiesConverter
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
package com.youlai.gateway.config;
|
package com.youlai.gateway.config;
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 白名单配置
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "white")
|
@ConfigurationProperties(prefix = "white-list")
|
||||||
public class WhiteUrlsConfig {
|
public class WhiteListConfig {
|
||||||
|
|
||||||
private List<String> urls;
|
private List<String> urls;
|
||||||
|
|
||||||
}
|
}
|
@ -14,15 +14,15 @@ import org.springframework.web.server.ServerWebExchange;
|
|||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将登录用户的JWT转换成用户信息过滤器
|
* JWT转换成用户信息过滤器
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
|
||||||
String token = exchange.getRequest().getHeaders().getFirst(AuthConstants.JWT_TOKEN_HEADER);
|
String token = exchange.getRequest().getHeaders().getFirst(AuthConstants.JWT_TOKEN_HEADER);
|
||||||
if (StrUtil.isBlank(token)) {
|
if (StrUtil.isBlank(token)) {
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.youlai.gateway.filter;
|
package com.youlai.gateway.filter;
|
||||||
|
|
||||||
import com.youlai.common.core.constant.AuthConstants;
|
import com.youlai.common.core.constant.AuthConstants;
|
||||||
import com.youlai.gateway.config.WhiteUrlsConfig;
|
import com.youlai.gateway.config.WhiteListConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -19,10 +19,10 @@ import java.util.List;
|
|||||||
* 白名单路径移除JWT请求头
|
* 白名单路径移除JWT请求头
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class WhiteUrlsRemoveJwtFilter implements WebFilter {
|
public class WhiteListRemoveJwtFilter implements WebFilter {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WhiteUrlsConfig whiteUrlsConfig;
|
private WhiteListConfig whiteListConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
@ -31,7 +31,7 @@ public class WhiteUrlsRemoveJwtFilter implements WebFilter {
|
|||||||
PathMatcher pathMatcher=new AntPathMatcher();
|
PathMatcher pathMatcher=new AntPathMatcher();
|
||||||
|
|
||||||
//白名单路径移除JWT请求头
|
//白名单路径移除JWT请求头
|
||||||
List<String> ignoreUrls = whiteUrlsConfig.getUrls();
|
List<String> ignoreUrls = whiteListConfig.getUrls();
|
||||||
for (String ignoreUrl : ignoreUrls) {
|
for (String ignoreUrl : ignoreUrls) {
|
||||||
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
if (pathMatcher.match(ignoreUrl, uri.getPath())) {
|
||||||
request = exchange.getRequest().mutate().header(AuthConstants.JWT_TOKEN_HEADER, "").build();
|
request = exchange.getRequest().mutate().header(AuthConstants.JWT_TOKEN_HEADER, "").build();
|
@ -1,59 +0,0 @@
|
|||||||
package com.youlai.gateway.handler;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.youlai.common.core.result.Result;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
|
||||||
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
|
|
||||||
*
|
|
||||||
* @author 冷酱
|
|
||||||
* @date 2020/5/26
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Order(-1)
|
|
||||||
@Configuration
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
|
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
|
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
|
||||||
|
|
||||||
if (response.isCommitted()) {
|
|
||||||
return Mono.error(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// header set
|
|
||||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
if (ex instanceof ResponseStatusException) {
|
|
||||||
response.setStatusCode(((ResponseStatusException) ex).getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.writeWith(Mono.fromSupplier(() -> {
|
|
||||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
|
||||||
try {
|
|
||||||
return bufferFactory.wrap(objectMapper.writeValueAsBytes(Result.error(ex.getMessage())));
|
|
||||||
}
|
|
||||||
catch (JsonProcessingException e) {
|
|
||||||
log.error("Error writing response", ex);
|
|
||||||
return bufferFactory.wrap(new byte[0]);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user