Commit 9b2b79bbd7268c8fd0611e75af1dacea15d7493f

Authored by 黄 x
1 parent 178bc581

fix:統一使用ThingsboardErrorResponseHandler进行异常捕获处理

Showing 13 changed files with 52 additions and 278 deletions
1   -package org.thingsboard.server.config.yunteng;
2   -
3   -import com.datastax.oss.driver.api.core.uuid.Uuids;
4   -import lombok.RequiredArgsConstructor;
5   -import lombok.extern.slf4j.Slf4j;
6   -import org.apache.http.HttpHeaders;
7   -import org.springframework.http.HttpStatus;
8   -import org.springframework.security.access.AccessDeniedException;
9   -import org.springframework.security.core.Authentication;
10   -import org.springframework.security.core.context.SecurityContextHolder;
11   -import org.springframework.web.bind.MethodArgumentNotValidException;
12   -import org.springframework.web.bind.annotation.ControllerAdvice;
13   -import org.springframework.web.bind.annotation.ExceptionHandler;
14   -import org.thingsboard.server.common.data.EntityType;
15   -import org.thingsboard.server.common.data.asset.Asset;
16   -import org.thingsboard.server.common.data.audit.ActionType;
17   -import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
18   -import org.thingsboard.server.common.data.exception.ThingsboardException;
19   -import org.thingsboard.server.common.data.id.EntityId;
20   -import org.thingsboard.server.common.data.yunteng.core.exception.*;
21   -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
22   -import org.thingsboard.server.common.data.yunteng.dto.SysLogOperateDTO;
23   -import org.thingsboard.server.dao.audit.AuditLogService;
24   -import org.thingsboard.server.exception.yunteng.YunTengErrorResponseHandler;
25   -import org.thingsboard.server.service.security.model.SecurityUser;
26   -import org.thingsboard.server.utils.yunteng.LogUtils;
27   -
28   -import javax.servlet.http.HttpServletRequest;
29   -import javax.servlet.http.HttpServletResponse;
30   -import java.util.Objects;
31   -import java.util.UUID;
32   -
33   -@ControllerAdvice(basePackages = "org.thingsboard.server.controller.yunteng")
34   -@RequiredArgsConstructor
35   -@Slf4j
36   -public class ControllerExceptionHandler {
37   -
38   - private final AuditLogService auditLogService;
39   - private final YunTengErrorResponseHandler errorResponseHandler;
40   -
41   - @ExceptionHandler(YunTengException.class)
42   - public void handleYunTengException(YunTengException ex,HttpServletRequest request, HttpServletResponse response) {
43   - produceLog( request, ex);
44   - errorResponseHandler.handle(ex, response);
45   - }
46   -
47   - @ExceptionHandler(MethodArgumentNotValidException.class)
48   - public void handleMethodArgumentNotValidException(
49   - MethodArgumentNotValidException ex,HttpServletRequest request, HttpServletResponse response) {
50   - produceLog( request, ex);
51   - errorResponseHandler.handle(
52   - new YunTengException(
53   - ErrorMessage.INVALID_PARAMETER.setMessage(
54   - Objects.requireNonNull(ex.getBindingResult().getFieldError()).getDefaultMessage()),
55   - HttpStatus.BAD_REQUEST),
56   - response);
57   - }
58   -
59   - @ExceptionHandler(YtDataValidationException.class)
60   - public void handleDataValidationException(
61   - YtDataValidationException ex, HttpServletRequest request, HttpServletResponse response) {
62   - produceLog( request, ex);
63   - YunTengException YunTengException =
64   - new YunTengException(
65   - ErrorMessage.BAD_PARAMETER.setMessage(ex.getMessage()), HttpStatus.BAD_REQUEST);
66   - errorResponseHandler.handle(YunTengException, response);
67   - }
68   -
69   - @ExceptionHandler(TooManyRequestException.class)
70   - public void handleTooManyRequestException(HttpServletResponse response) {
71   - errorResponseHandler.handle(
72   - new YunTengException(ErrorMessage.TOO_MANY_REQUEST, HttpStatus.TOO_MANY_REQUESTS),
73   - response);
74   - }
75   -
76   - @ExceptionHandler(AccessDeniedException.class)
77   - public void handleAccessDeniedException(AccessDeniedException ex,HttpServletRequest request, HttpServletResponse response) {
78   - produceLog( request, ex);
79   - errorResponseHandler.handle(
80   - new YunTengException(
81   - ErrorMessage.ACCESS_DENIED.setMessage(ex.getMessage()), HttpStatus.FORBIDDEN),
82   - response);
83   - }
84   -
85   - @ExceptionHandler(NoneTenantAssetException.class)
86   - public void handleNoneTenantAssetException(
87   - NoneTenantAssetException ex, HttpServletRequest request, HttpServletResponse response) {
88   - produceLog( request, ex);
89   - errorResponseHandler.handle(
90   - new YunTengException(
91   - ErrorMessage.NONE_TENANT_ASSET.setMessage(ex.getMessage()), HttpStatus.NOT_FOUND),
92   - response);
93   - }
94   -
95   - @ExceptionHandler(EntityCreationException.class)
96   - public void handleEntityCreationException(HttpServletResponse response) {
97   - errorResponseHandler.handle(
98   - new YunTengException(
99   - ErrorMessage.SEND_DESTINATION_NOT_FOUND, HttpStatus.BAD_REQUEST),
100   - response);
101   - }
102   -
103   -
104   -
105   - protected SecurityUser getCurrentUser() throws ThingsboardException {
106   - Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
107   - if (authentication != null && authentication.getPrincipal() instanceof SecurityUser) {
108   - return (SecurityUser) authentication.getPrincipal();
109   - } else {
110   - throw new ThingsboardException("You aren't authorized to perform this operation!", ThingsboardErrorCode.AUTHENTICATION);
111   - }
112   - }
113   -
114   - /**
115   - * 生产日志并缓存到队列中
116   - *
117   - * @param request 响应头
118   - * @param e 异常信息
119   - */
120   - void produceLog(HttpServletRequest request, Exception e) {
121   -
122   - try {
123   - SecurityUser currentUser = getCurrentUser();
124   -
125   - Asset entity = new Asset();
126   - entity.setName(e.getMessage());
127   -
128   - //请求相关信息
129   - SysLogOperateDTO additionalInfo = new SysLogOperateDTO();
130   - additionalInfo.setApi(request.getRequestURI());
131   - additionalInfo.setClientIp(LogUtils.clientIP(request));
132   - additionalInfo.setServerIp(LogUtils.serverIP());
133   - additionalInfo.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
134   - additionalInfo.setMethod(request.getMethod());
135   -
136   -
137   - EntityId operateId = new EntityId() {
138   - @Override
139   - public UUID getId() {
140   - return Uuids.timeBased();
141   - }
142   -
143   - @Override
144   - public EntityType getEntityType() {
145   - return EntityType.RUNNING_EXCEPTION;
146   - }
147   - };
148   -
149   -
150   - auditLogService.logEntityAction(currentUser.getTenantId(),currentUser.getCustomerId(),currentUser.getId(), currentUser.getName(), operateId,entity, ActionType.LOG_EXCEPTION,e,additionalInfo);
151   - } catch (ThingsboardException ex) {
152   - log.error("异常日志记录异常【{}】",ex);
153   - }
154   -
155   - }
156   -}
... ... @@ -40,6 +40,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
40 40 import org.springframework.web.util.WebUtils;
41 41 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
42 42 import org.thingsboard.server.common.data.exception.ThingsboardException;
  43 +import org.thingsboard.server.common.data.yunteng.core.Result;
  44 +import org.thingsboard.server.common.data.yunteng.core.exception.ThingsKitException;
43 45 import org.thingsboard.server.common.msg.tools.TbRateLimitsException;
44 46 import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException;
45 47 import org.thingsboard.server.service.security.exception.JwtExpiredTokenException;
... ... @@ -130,7 +132,10 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand
130 132 handleAccessDeniedException(response);
131 133 } else if (exception instanceof AuthenticationException) {
132 134 handleAuthenticationException((AuthenticationException) exception, response);
133   - } else {
  135 + }else if(exception instanceof ThingsKitException){
  136 + handleThingsKitException((ThingsKitException)exception, response);
  137 + }
  138 + else {
134 139 response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
135 140 mapper.writeValue(response.getWriter(), ThingsboardErrorResponse.of(exception.getMessage(),
136 141 ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR));
... ... @@ -208,4 +213,10 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand
208 213 }
209 214 }
210 215
  216 + private void handleThingsKitException(ThingsKitException exception ,HttpServletResponse response) throws IOException {
  217 + response.setStatus((exception).getHttpStatus().value());
  218 + mapper.writeValue(
  219 + response.getWriter(), Result.error(( exception).getError()));
  220 + }
  221 +
211 222 }
... ...
1   -package org.thingsboard.server.exception.yunteng;
2   -
3   -import com.fasterxml.jackson.databind.ObjectMapper;
4   -import lombok.extern.slf4j.Slf4j;
5   -import org.springframework.beans.factory.annotation.Autowired;
6   -import org.springframework.http.HttpStatus;
7   -import org.springframework.http.MediaType;
8   -import org.springframework.security.access.AccessDeniedException;
9   -import org.springframework.security.authentication.BadCredentialsException;
10   -import org.springframework.security.authentication.DisabledException;
11   -import org.springframework.security.authentication.LockedException;
12   -import org.springframework.security.core.AuthenticationException;
13   -import org.springframework.security.web.access.AccessDeniedHandler;
14   -import org.springframework.stereotype.Component;
15   -import org.thingsboard.server.common.data.yunteng.core.Result;
16   -import org.thingsboard.server.common.data.yunteng.core.exception.YunTengException;
17   -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
18   -import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException;
19   -import org.thingsboard.server.service.security.exception.JwtExpiredTokenException;
20   -
21   -import javax.servlet.http.HttpServletRequest;
22   -import javax.servlet.http.HttpServletResponse;
23   -import java.io.IOException;
24   -
25   -@Component
26   -@Slf4j
27   -public class YunTengErrorResponseHandler implements AccessDeniedHandler {
28   -
29   - private final ObjectMapper mapper;
30   -
31   - @Autowired
32   - public YunTengErrorResponseHandler(ObjectMapper mapper) {
33   - this.mapper = mapper;
34   - }
35   -
36   - @Override
37   - public void handle(
38   - HttpServletRequest request,
39   - HttpServletResponse response,
40   - AccessDeniedException accessDeniedException)
41   - throws IOException {
42   - if (!response.isCommitted()) {
43   - response.setContentType(MediaType.APPLICATION_JSON_VALUE);
44   - response.setStatus(HttpStatus.FORBIDDEN.value());
45   - mapper.writeValue(response.getWriter(), Result.error(ErrorMessage.NO_PERMISSION));
46   - }
47   - }
48   -
49   - public void handle(Exception exception, HttpServletResponse response) {
50   - log.debug("Processing exception {}", exception.getMessage(), exception);
51   - if (!response.isCommitted()) {
52   - try {
53   - response.setCharacterEncoding("utf-8");
54   - response.setContentType(MediaType.APPLICATION_JSON_VALUE);
55   -
56   - if (exception instanceof AccessDeniedException) {
57   - response.setStatus(HttpStatus.FORBIDDEN.value());
58   - mapper.writeValue(response.getWriter(), Result.error(ErrorMessage.ACCESS_DENIED));
59   - } else if (exception instanceof AuthenticationException) {
60   - handleAuthenticationException((AuthenticationException) exception, response);
61   - } else if (exception instanceof YunTengException) {
62   - response.setStatus(((YunTengException) exception).getHttpStatus().value());
63   - mapper.writeValue(
64   - response.getWriter(), Result.error(((YunTengException) exception).getError()));
65   - } else {
66   - response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
67   - mapper.writeValue(response.getWriter(), Result.error(exception.getMessage()));
68   - }
69   - } catch (IOException e) {
70   - log.error("Can't handle exception", e);
71   - }
72   - }
73   - }
74   -
75   - private void handleAuthenticationException(
76   - AuthenticationException authenticationException, HttpServletResponse response)
77   - throws IOException {
78   - response.setStatus(HttpStatus.UNAUTHORIZED.value());
79   - if (authenticationException instanceof BadCredentialsException) {
80   - mapper.writeValue(
81   - response.getWriter(), Result.error(ErrorMessage.USERNAME_PASSWORD_INCORRECT));
82   - } else if (authenticationException instanceof DisabledException) {
83   - mapper.writeValue(response.getWriter(), Result.error(ErrorMessage.ACCOUNT_DISABLED));
84   - } else if (authenticationException instanceof LockedException) {
85   - mapper.writeValue(response.getWriter(), Result.error(ErrorMessage.ACCOUNT_DISABLED));
86   - } else if (authenticationException instanceof JwtExpiredTokenException) {
87   - mapper.writeValue(response.getWriter(), Result.error(ErrorMessage.TOKEN_EXPIRED));
88   - } else if (authenticationException instanceof AuthMethodNotSupportedException) {
89   - mapper.writeValue(
90   - response.getWriter(), Result.error(ErrorMessage.AUTHENTICATION_METHOD_NOT_SUPPORTED));
91   - } else {
92   - mapper.writeValue(
93   - response.getWriter(),
94   - Result.error(HttpStatus.UNAUTHORIZED.value(), authenticationException.getMessage()));
95   - }
96   - }
97   -}
1 1 package org.thingsboard.server.common.data.yunteng.core.exception;
2 2
3   -public class EntityCreationException extends RuntimeException {
  3 +import org.springframework.http.HttpStatus;
  4 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  5 +
  6 +public class EntityCreationException extends ThingsKitException {
4 7
5 8 private static final long serialVersionUID = 5255597864949518781L;
6 9
7 10 public EntityCreationException(String message) {
8   - super(message);
  11 + super(ErrorMessage.BAD_PARAMETER.setMessage(message), HttpStatus.BAD_REQUEST);
9 12 }
10 13 }
... ...
1 1 package org.thingsboard.server.common.data.yunteng.core.exception;
2 2
3   -public class FileNotFoundException extends RuntimeException{
  3 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  4 +
  5 +public class FileNotFoundException extends ThingsKitException {
4 6 private static final long serialVersionUID = 3466865879043055822L;
5 7
6   - public FileNotFoundException(String message) {
  8 + public FileNotFoundException(ErrorMessage message) {
7 9 super(message);
8 10 }
9 11 }
... ...
1 1 package org.thingsboard.server.common.data.yunteng.core.exception;
2 2
3   -public class FileStorageException extends RuntimeException{
  3 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  4 +
  5 +public class FileStorageException extends ThingsKitException {
4 6 private static final long serialVersionUID = -8866081834891143120L;
5 7
6   - public FileStorageException(String message) {
  8 + public FileStorageException(ErrorMessage message) {
7 9 super(message);
8 10 }
9 11 }
... ...
1 1 package org.thingsboard.server.common.data.yunteng.core.exception;
2 2
3   -public class NoneTenantAssetException extends RuntimeException {
  3 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  4 +
  5 +public class NoneTenantAssetException extends ThingsKitException {
4 6 private static final long serialVersionUID = 9135599998185288967L;
5 7
6   - public NoneTenantAssetException(String message) {
  8 + public NoneTenantAssetException(ErrorMessage message) {
7 9 super(message);
8 10 }
9 11 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/core/exception/ThingsKitException.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/yunteng/core/exception/YunTengException.java
... ... @@ -4,26 +4,27 @@ import lombok.Getter;
4 4 import org.springframework.http.HttpStatus;
5 5 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
6 6
7   -public class YunTengException extends RuntimeException {
  7 +public class ThingsKitException extends RuntimeException {
8 8 private static final long serialVersionUID = 4036257507478854844L;
9 9
10 10 @Getter private final HttpStatus httpStatus;
11 11
12 12 @Getter private final ErrorMessage error;
13 13
14   - public YunTengException(ErrorMessage errorMessage) {
  14 +
  15 + public ThingsKitException(ErrorMessage errorMessage) {
15 16 super(errorMessage.getMessage());
16   - this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
  17 + this.httpStatus = HttpStatus.BAD_REQUEST;
17 18 this.error = errorMessage;
18 19 }
19 20
20   - public YunTengException(ErrorMessage errorMessage, HttpStatus httpStatus) {
  21 + public ThingsKitException(ErrorMessage errorMessage, HttpStatus httpStatus) {
21 22 super(errorMessage.getMessage());
22 23 this.httpStatus = httpStatus;
23 24 this.error = errorMessage;
24 25 }
25 26
26   - public YunTengException() {
  27 + public ThingsKitException() {
27 28 super(ErrorMessage.INTERNAL_ERROR.getMessage());
28 29 this.error = ErrorMessage.INTERNAL_ERROR;
29 30 this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
... ...
1 1 package org.thingsboard.server.common.data.yunteng.core.exception;
2 2
3 3 import lombok.Getter;
  4 +import org.springframework.http.HttpStatus;
  5 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
4 6
5   -public class YtDataValidationException extends RuntimeException {
  7 +public class YtDataValidationException extends ThingsKitException {
6 8 private static final long serialVersionUID = 3556952261254572635L;
7 9
8 10 @Getter public boolean log = false;
9 11
10 12 public YtDataValidationException(String message) {
11   - super(message);
  13 + super(ErrorMessage.BAD_PARAMETER.setMessage(message));
12 14 }
13 15
14 16 public YtDataValidationException(String message, boolean log) {
15   - super(message);
  17 + super(ErrorMessage.BAD_PARAMETER.setMessage(message));
16 18 this.log = log;
17 19 }
18 20 }
... ...
... ... @@ -52,6 +52,9 @@ public enum ErrorMessage {
52 52 ORGANIZATION_EXISTED_SCENE_REACT(400033,"组织被场景联动使用中"),
53 53 ORGANIZATION_EXISTED_ALARM_CONTACT(400034,"组织被告警联系人使用中"),
54 54 EXIST_LEADER_MEMBER_RELATION(400035,"上下级之间有一种关系"),
  55 + FILE_NOT_FOUND(400036,"文件未找到"),
  56 + STORE_FILE_FAILED(400037,"文件存储失败"),
  57 + NOT_BELONG_CURRENT_TENANT(400038,"该用户不属于当前租户"),
55 58 HAVE_NO_PERMISSION(500002,"没有修改权限");
56 59 private final int code;
57 60 private String message;
... ...
... ... @@ -16,6 +16,7 @@ import org.springframework.web.multipart.MultipartFile;
16 16 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
17 17 import org.thingsboard.server.common.data.yunteng.core.exception.FileNotFoundException;
18 18 import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException;
  19 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
19 20 import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
20 21
21 22 import javax.servlet.http.HttpServletRequest;
... ... @@ -69,8 +70,7 @@ public class LocalFileStorageService implements FileStorageService {
69 70 }
70 71 // Check if the file's name contains invalid characters
71 72 if (fileName.contains("..")) {
72   - throw new FileStorageException(
73   - "Sorry! Filename contains invalid path sequence " + fileName);
  73 + throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED);
74 74 }
75 75
76 76 // Copy file to the target location (Replacing existing file with the same name)
... ... @@ -79,7 +79,7 @@ public class LocalFileStorageService implements FileStorageService {
79 79
80 80 return fileName;
81 81 } catch (IOException ex) {
82   - throw new FileStorageException("Could not store file " + fileName + ". Please try again!");
  82 + throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED);
83 83 }
84 84 }
85 85
... ... @@ -90,10 +90,10 @@ public class LocalFileStorageService implements FileStorageService {
90 90 if (resource.exists()) {
91 91 return resource;
92 92 } else {
93   - throw new FileNotFoundException("File not found " + fileName);
  93 + throw new FileNotFoundException(ErrorMessage.FILE_NOT_FOUND);
94 94 }
95 95 } catch (MalformedURLException ex) {
96   - throw new FileNotFoundException("File not found " + fileName);
  96 + throw new FileNotFoundException(ErrorMessage.FILE_NOT_FOUND);
97 97 }
98 98 }
99 99
... ...
... ... @@ -15,6 +15,7 @@ import org.springframework.web.context.request.RequestContextHolder;
15 15 import org.springframework.web.context.request.ServletRequestAttributes;
16 16 import org.springframework.web.multipart.MultipartFile;
17 17 import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException;
  18 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
18 19 import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
19 20
20 21 import javax.servlet.http.HttpServletRequest;
... ... @@ -59,7 +60,7 @@ public class MinioFileStorageService implements FileStorageService {
59 60 }
60 61 // Check if the file's name contains invalid characters
61 62 if (fileName.contains("..")) {
62   - throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
  63 + throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED);
63 64 }
64 65
65 66 // 储存
... ... @@ -76,7 +77,7 @@ public class MinioFileStorageService implements FileStorageService {
76 77 return fileName;
77 78 } catch (Exception ex) {
78 79 ex.printStackTrace();
79   - throw new FileStorageException("Could not store file " + fileName + ". Please try again!");
  80 + throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED);
80 81 }
81 82 }
82 83
... ...
... ... @@ -282,7 +282,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User>
282 282 public UserDTO updateUser(UserDTO userDTO, boolean isPtSysadmin, String tenantId) {
283 283 User user = baseMapper.selectById(userDTO.getId());
284 284 if (!isPtSysadmin && !user.getTenantId().equals(tenantId)) {
285   - throw new NoneTenantAssetException("this user not belong to current tenant");
  285 + throw new NoneTenantAssetException(ErrorMessage.NOT_BELONG_CURRENT_TENANT);
286 286 }
287 287 if (!user.getUsername().equals(userDTO.getUsername())) {
288 288 throw new YtDataValidationException(ErrorMessage.USERNAME_IS_IMMUTABLE.getMessage());
... ...