先前我们建立的StockAPI在解析token字串时,并没有针对解析错误的情况去做错误处理,所以如果签证过期的话就会出现
在错误处理方面,Spring Boot上面有提供API的错误处理,
还记得我们之前实作JWTCheckFilter的范例吗?
由於我们此次的错误是从filter抛出的,因此只透过@RestControllerAdvice
和@ExceptionHandler是捕捉不到错误的,原因是ControllerAdvice只能捕捉到从有@Controller这个注解类抛出的错误,而从更外层的filter产生的错误以下提供两种思路去捕捉错误
1.透过实作ErrorController(就是会出现white label页的控制类),使filter抛出的错误重新回到
@Controller控制类的底下,ControllerAdvice就可以捕捉
2.在filter用try-catch捕捉错误後直接写出结果
在这边我们实作第一种方法
先实作ErrorController类
package com.stockAPI.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TokenErrorControllerImpl implements ErrorController {
@RequestMapping("/error")
public void handleError(HttpServletRequest request) throws Throwable {
//只要遇到exception就直接抛出
if (request.getAttribute("javax.servlet.error.exception") != null) {
throw (Throwable) request.getAttribute("javax.servlet.error.exception");
}
}
}
@RestControllerAdvice -BaseHandler
package com.stockAPI.exceptionHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.stockAPI.enumsave.TokenEnum;
import com.stockAPI.exception.TokenException;
import com.stockAPI.model.APIReturnObject;
import io.jsonwebtoken.ExpiredJwtException;
@RestControllerAdvice
public class BaseHandler {
static Logger logger = LogManager.getLogger();
// 登入验证错误
@ExceptionHandler(UsernameNotFoundException.class)
public ResponseEntity<APIReturnObject> usernameNotFoundException(UsernameNotFoundException e) {
APIReturnObject aPIReturnObject = new APIReturnObject();
aPIReturnObject.setMessage(e.getMessage());
return new ResponseEntity<APIReturnObject>(aPIReturnObject, HttpStatus.FORBIDDEN);
}
// token过期
@ExceptionHandler(ExpiredJwtException.class)
public ResponseEntity<APIReturnObject> expiredJwtException(ExpiredJwtException e) {
APIReturnObject aPIReturnObject = new APIReturnObject();
aPIReturnObject.setMessage(TokenEnum.TOKEN_ERROR_EXPIRED.getMessage());
return new ResponseEntity<APIReturnObject>(aPIReturnObject, HttpStatus.REQUEST_TIMEOUT);
}
// 身分验证有误
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<APIReturnObject> AuthenticationException(AuthenticationException e) {
logger.error(e.getMessage());
APIReturnObject aPIReturnObject = new APIReturnObject();
aPIReturnObject.setMessage(TokenEnum.TOKEN_AUTH_FAIL.getMessage());
return new ResponseEntity<APIReturnObject> (aPIReturnObject,TokenEnum.TOKEN_AUTH_FAIL.getHttpstatus());
}
}
TokenEnum-储存回传讯息和状态码
package com.stockAPI.enumsave;
import org.springframework.http.HttpStatus;
public enum TokenEnum {
Token_SUCCESS(200,"tokem资讯取得成功",HttpStatus.OK),
TOKEN_ERROR_EXPIRED(1000,"token验证过期",HttpStatus.REQUEST_TIMEOUT),//httpstatus 408
TOKEN_AUTH_FAIL(1001,"身分验证发生错误",HttpStatus.FORBIDDEN);//httpstatus 403
private Integer code;
private String message;
private HttpStatus httpstatus;
private TokenEnum( Integer code, String message,HttpStatus httpstatus) {
this.code = code;
this.message = message;
this.httpstatus =httpstatus;
}
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
public HttpStatus getHttpstatus() {
return httpstatus;
}
}
在传送一次post请求就可以发现回传的格式和状态码已经改变
想了解更多的例外处理和filter可以推荐看这两篇
参考资料
How to manage exceptions thrown in filters in Spring?
<<: 用 Python 畅玩 Line bot - 20:图文选单
>>: Day38 ATT&CK for ICS - Impact(4)
前言: 昨天我们介绍了一个普通的资讯页面是如何完成的,今天我们要来介绍另一个很常用到的页面种类,资...
一转眼已经到第18天了,照这个速度可能没办法完成一个网站,今天要来赶进度! 首先要勘误 在nonce...
在架设 Hexo 之前,有些前置作业要先进行。其中由於 Hexo 是使用 Node.js 撰写,并且...
23 - Design Pattern(3) - Builder Builder pattern 常...
Version Control System (VCS) Centralized Version C...