1 前言
上一章我们已经按照与前端的约定自定义了token的返回格式。同样的,程序在运行过程中会产生各种异常,这些默认的异常对前端非常的不友好,比如默认的Oauth2异常response的status=4XX,返回的格式如下:
{
"error": "invalid_grant",
"error_description": "Bad credentials"
}
现在我们同样要把异常的返回格式改为与前端约定的格式,并且让response的status=200,这样便于前端对ajax访问时的异常进行统一处理。目标格式如下?
{
"code": 4xx,
"msg": "msg",
"data": null;
}
我们需要处理两方面的异常,一个是授权认证服务器的异常,也就是获取token时的异常,包括帐号不存在、密码错误、验证码错误、client错误等等。另一个是资源服务器的异常,比如权限不足,token过期等等。下面我们就来对这两方面进行改造。
2 认证服务器异常
2.1 定义自已的异常处理类
定义MyOauthException继承OAuth2Exception,代码如下:
package com.example.oauth2.exception;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
@JsonSerialize(using = MyOauthExceptionSerializer.class)
public class MyOauthException extends OAuth2Exception {
public MyOauthException(String msg, Throwable t) {
super(msg, t);
}
public MyOauthException(String msg) {
super(msg);
}
}
2.2 序列化异常处理类
定义MyOauthExceptionSerializer序列化MyOauthException,代码如下:
package com.example.oauth2.exception;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class MyOauthExceptionSerializer extends StdSerializer<MyOauthException> {
protected MyOauthExceptionSerializer() {
super(MyOauthException.class);
}
@Override
public void serialize(MyOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("code", String.valueOf(e.getHttpErrorCode()));
jsonGenerator.writeStringField("msg", e.getMessage());
jsonGenerator.writeStringField("data",null);
jsonGenerator.writeEndObject();
}
}
2.3 异常捕获并通过MyOauthException处理
新建MyOauthWebResponseExceptionTranslator继承WebResponseExceptionTranslator,从异常栈中获取各种类型的异常并用我们自定义的MyOauthException进行处理,代码如下:
package com.example.oauth2.exception;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import java.io.IOException;
@Component
public class MyOauthWebResponseExceptionTranslator imp