فهرست منبع

oauth2相关接口自定义请求返回结果集

ZhangWenQiang 5 سال پیش
والد
کامیت
7e8fb1456c

+ 19 - 0
happy-cloud-auth/src/main/java/org/jeecg/common/exception/UserOAuth2Exception.java

@@ -0,0 +1,19 @@
+package org.jeecg.common.exception;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2020/8/3 14:58
+ * @Description: OAuth2Exception异常处理类
+ */
+@Slf4j
+public class UserOAuth2Exception {
+
+    public static Result<?> handleOauth2(OAuth2Exception e) {
+        log.error("Oauth2异常===========", e.getMessage());
+        return Result.error(e.getMessage());
+    }
+}

+ 6 - 1
happy-cloud-auth/src/main/java/org/jeecg/config/AuthorizationServerConfig.java

@@ -18,6 +18,7 @@ import org.springframework.security.oauth2.config.annotation.web.configurers.Aut
 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
 import org.springframework.security.oauth2.provider.ClientDetailsService;
 import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
+import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
 import org.springframework.security.oauth2.provider.token.TokenStore;
 import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
@@ -77,6 +78,9 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
     @Autowired
     private BCryptPasswordEncoder passwordEncoder;
 
+    @Autowired
+    private WebResponseExceptionTranslator webResponseExceptionTranslator;
+
     /**
      * 定义客户详细信息服务的配置器
      *
@@ -122,7 +126,8 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
                 .tokenStore(tokenStore())
                 .userDetailsService(userDetailsService)
                 .authenticationManager(authenticationManager)
-                .pathMapping(EndpointConstant.OAUTH_TOKEN, EndpointConstant.OAUTH_TOKEN);
+                .pathMapping(EndpointConstant.OAUTH_TOKEN, EndpointConstant.OAUTH_TOKEN)
+                .exceptionTranslator(webResponseExceptionTranslator);
     }
 
     /**

+ 141 - 0
happy-cloud-auth/src/main/java/org/jeecg/handler/OAuth2WebResponseExceptionTranslator.java

@@ -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;
+        }
+    }
+
+}

+ 29 - 0
happy-cloud-auth/src/main/java/org/jeecg/handler/Oauth2ExceptionHandler.java

@@ -0,0 +1,29 @@
+package org.jeecg.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2020/8/3 13:27
+ * @Description: 全局处理Oauth2抛出的异常(走不到这里,问题暂未找到)
+ */
+@RestControllerAdvice
+@Slf4j
+public class Oauth2ExceptionHandler {
+
+    /**
+     * 全局处理Oauth2抛出的异常
+     *
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(value = OAuth2Exception.class)
+    public Result<?> handleOauth2(OAuth2Exception e) {
+        log.error("Oauth2异常===========", e.getMessage());
+        return Result.error(e.getMessage());
+    }
+}

+ 46 - 0
happy-cloud-auth/src/main/java/org/jeecg/modules/auth/controller/AuthController.java

@@ -0,0 +1,46 @@
+package org.jeecg.modules.auth.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.auth.entity.OauthTokenDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.Principal;
+import java.util.Map;
+
+/**
+ * @Description: 自定义实现Oauth2默认的登录认证接口
+ * @Author: zwq
+ * @Date: 2020-06-12
+ * @Version: V1.0
+ */
+@RestController
+@RequestMapping("/oauth")
+@Slf4j
+public class AuthController {
+
+    @Autowired
+    private TokenEndpoint tokenEndpoint;
+
+    /**
+     * Oauth2登录认证
+     */
+    @RequestMapping(value = "/token", method = RequestMethod.POST)
+    public Result<?> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
+        log.info("登录认证=====,{}", principal);
+        OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
+        OauthTokenDto oauth2TokenDto = OauthTokenDto.builder()
+                .accessToken(oAuth2AccessToken.getValue())
+                .expiresIn(oAuth2AccessToken.getExpiresIn())
+                .scope("all")
+                .tokenType(oAuth2AccessToken.getTokenType()).build();
+        return Result.ok(oauth2TokenDto);
+    }
+}

+ 4 - 0
happy-cloud-auth/src/main/java/org/jeecg/modules/auth/entity/OauthClientDetails.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
 
 import java.io.Serializable;
 
@@ -13,6 +15,8 @@ import java.io.Serializable;
  */
 @Data
 @TableName("oauth_client_details")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
 public class OauthClientDetails implements Serializable {
     private static final long serialVersionUID = 1L;
     /**

+ 39 - 0
happy-cloud-auth/src/main/java/org/jeecg/modules/auth/entity/OauthTokenDto.java

@@ -0,0 +1,39 @@
+package org.jeecg.modules.auth.entity;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author zwq
+ * @date 2020-05-22
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Builder
+public class OauthTokenDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 访问令牌
+     */
+    private String accessToken;
+
+    /**
+     * 有效时间(秒)
+     */
+    private int expiresIn;
+
+    /**
+     * token类型
+     */
+    private String tokenType;
+
+    /**
+     * 作用范围
+     */
+    private String scope;
+}