StockAPI-错误讯息处理 (Day32)

先前我们建立的StockAPI在解析token字串时,并没有针对解析错误的情况去做错误处理,所以如果签证过期的话就会出现

https://ithelp.ithome.com.tw/upload/images/20211024/20138857NtxiFROki5.png

在错误处理方面,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请求就可以发现回传的格式和状态码已经改变

https://ithelp.ithome.com.tw/upload/images/20211024/20138857Brv9duaWDc.png


想了解更多的例外处理和filter可以推荐看这两篇

Day 17 - Spring Boot 例外处理

Day 21 - Spring Boot & Filter

参考资料

How to manage exceptions thrown in filters in Spring?


<<:  用 Python 畅玩 Line bot - 20:图文选单

>>:  Day38 ATT&CK for ICS - Impact(4)

DAY24-资讯卡页面设计

前言: 昨天我们介绍了一个普通的资讯页面是如何完成的,今天我们要来介绍另一个很常用到的页面种类,资...

[Day 18] - 初探永丰银行线上收款API - 丰收款 - 建立订单!

一转眼已经到第18天了,照这个速度可能没办法完成一个网站,今天要来赶进度! 首先要勘误 在nonce...

Day 3:安装 Hexo 前置作业:Node.js、Git、网页编辑器 VS code、文章编辑器 Typora

在架设 Hexo 之前,有些前置作业要先进行。其中由於 Hexo 是使用 Node.js 撰写,并且...

冒险村23 - Design Pattern(3) - Builder

23 - Design Pattern(3) - Builder Builder pattern 常...

[Git] Intro

Version Control System (VCS) Centralized Version C...