|
|
@@ -0,0 +1,141 @@
|
|
|
+package org.jeecg.handler;
|
|
|
+
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.jeecg.common.api.vo.Result;
|
|
|
+import org.jeecg.common.exception.UserOAuth2Exception;
|
|
|
+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.core.AuthenticationException;
|
|
|
+import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
|
|
|
+import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
|
|
|
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
|
|
+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;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Author: zwq
|
|
|
+ * @Date: Create in 2020/8/3 15:00
|
|
|
+ * @Description:
|
|
|
+ */
|
|
|
+@Component
|
|
|
+@Slf4j
|
|
|
+public class OAuth2WebResponseExceptionTranslator implements WebResponseExceptionTranslator {
|
|
|
+ private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResponseEntity translate(Exception e) throws Exception {
|
|
|
+ Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(e);
|
|
|
+ Exception ase = (OAuth2Exception) this.throwableAnalyzer.getFirstThrowableOfType(OAuth2Exception.class, causeChain);
|
|
|
+ //异常链中有OAuth2Exception异常
|
|
|
+ if (ase != null) {
|
|
|
+ return this.handleOAuth2Exception((OAuth2Exception) ase);
|
|
|
+ }
|
|
|
+ //身份验证相关异常
|
|
|
+ ase = (AuthenticationException) this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
|
|
|
+ if (ase != null) {
|
|
|
+ return this.handleOAuth2Exception(new OAuth2WebResponseExceptionTranslator.UnauthorizedException(e.getMessage(), e));
|
|
|
+ }
|
|
|
+ //异常链中包含拒绝访问异常
|
|
|
+ ase = (AccessDeniedException) this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
|
|
|
+ if (ase instanceof AccessDeniedException) {
|
|
|
+ return this.handleOAuth2Exception(new OAuth2WebResponseExceptionTranslator.ForbiddenException(ase.getMessage(), ase));
|
|
|
+ }
|
|
|
+ //异常链中包含Http方法请求异常
|
|
|
+ ase = (HttpRequestMethodNotSupportedException) this.throwableAnalyzer.getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain);
|
|
|
+ if (ase instanceof HttpRequestMethodNotSupportedException) {
|
|
|
+ return this.handleOAuth2Exception(new OAuth2WebResponseExceptionTranslator.MethodNotAllowed(ase.getMessage(), ase));
|
|
|
+ }
|
|
|
+ return this.handleOAuth2Exception(new OAuth2WebResponseExceptionTranslator.ServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), e));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OAuth2Exception异常处理
|
|
|
+ *
|
|
|
+ * @param e
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception e) throws IOException {
|
|
|
+ int status = e.getHttpErrorCode();
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.set("Cache-Control", "no-store");
|
|
|
+ headers.set("Pragma", "no-cache");
|
|
|
+ if (status == HttpStatus.UNAUTHORIZED.value() || e instanceof InsufficientScopeException) {
|
|
|
+ headers.set("WWW-Authenticate", String.format("%s %s", "Bearer", e.getSummary()));
|
|
|
+ }
|
|
|
+ Result<?> exception = UserOAuth2Exception.handleOauth2(e);
|
|
|
+ ResponseEntity<OAuth2Exception> response = new ResponseEntity(exception, headers, HttpStatus.valueOf(status));
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class MethodNotAllowed extends OAuth2Exception {
|
|
|
+ public MethodNotAllowed(String msg, Throwable t) {
|
|
|
+ super(msg, t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getOAuth2ErrorCode() {
|
|
|
+ return "method_not_allowed";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getHttpErrorCode() {
|
|
|
+ return 405;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class UnauthorizedException extends OAuth2Exception {
|
|
|
+ public UnauthorizedException(String msg, Throwable t) {
|
|
|
+ super(msg, t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getOAuth2ErrorCode() {
|
|
|
+ return "unauthorized";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getHttpErrorCode() {
|
|
|
+ return 401;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class ServerErrorException extends OAuth2Exception {
|
|
|
+ public ServerErrorException(String msg, Throwable t) {
|
|
|
+ super(msg, t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getOAuth2ErrorCode() {
|
|
|
+ return "server_error";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getHttpErrorCode() {
|
|
|
+ return 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class ForbiddenException extends OAuth2Exception {
|
|
|
+ public ForbiddenException(String msg, Throwable t) {
|
|
|
+ super(msg, t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getOAuth2ErrorCode() {
|
|
|
+ return "access_denied";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getHttpErrorCode() {
|
|
|
+ return 403;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|