瀏覽代碼

fix:代码冲突解决

wangbo 3 年之前
父節點
當前提交
781e554974

+ 10 - 0
pom.xml

@@ -113,6 +113,16 @@
             <version>5.3.2</version>
             <scope>compile</scope>
         </dependency>
+        <!--HttpClient -->
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 20 - 0
src/main/java/com/inspur/smsb/gateway/dto/CredentialRepresentation.java

@@ -0,0 +1,20 @@
+package com.inspur.smsb.gateway.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class CredentialRepresentation implements Serializable {
+
+    private static final long serialVersionUID = 827765174163306918L;
+    private Integer createdDate;
+    private String credentialData;
+    private String id;
+    private Integer priority;
+    private String secretData;
+    private Boolean temporary;
+    private String type;
+    private String userLabel;
+    private String value;
+}

+ 13 - 0
src/main/java/com/inspur/smsb/gateway/dto/FederatedIdentityRepresentation.java

@@ -0,0 +1,13 @@
+package com.inspur.smsb.gateway.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class FederatedIdentityRepresentation implements Serializable {
+    private static final long serialVersionUID = 3972637911173038811L;
+    private String identityProvider;
+    private String userId;
+    private String userName;
+}

+ 36 - 0
src/main/java/com/inspur/smsb/gateway/dto/KeycloakUserDto.java

@@ -0,0 +1,36 @@
+package com.inspur.smsb.gateway.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class KeycloakUserDto implements Serializable {
+    private static final long serialVersionUID = 7074906195276434617L;
+    private Map access;
+    private Map attributes;
+    private List<UserConsentRepresentation> clientConsents;
+    private Map clientRoles;
+    private Long createdTimestamp;
+    private List<CredentialRepresentation> credentials;
+    private List<String> disableableCredentialTypes;
+    private String email;
+    private Boolean emailVerified;
+    private Boolean enabled;
+    private List<FederatedIdentityRepresentation> federatedIdentities;
+    private String federationLink;
+    private String firstName;
+    private List<String> groups;
+    private String id;
+    private String lastName;
+    private Integer notBefore;
+    private String origin;
+    private List<String> realmRoles;
+    private List<String> requiredActions;
+    private String self;
+    private String serviceAccountClientId;
+    private String username;
+
+}

+ 16 - 0
src/main/java/com/inspur/smsb/gateway/dto/UserConsentRepresentation.java

@@ -0,0 +1,16 @@
+package com.inspur.smsb.gateway.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class UserConsentRepresentation implements Serializable {
+
+    private static final long serialVersionUID = 120521657515643111L;
+    private String clientId;
+    private Integer createdDate;
+    private List<String> grantedClientScopes;
+    private Integer lastUpdatedDate;
+}

+ 99 - 23
src/main/java/com/inspur/smsb/gateway/filter/WebFluxUserRequestInfoFilter.java

@@ -1,19 +1,27 @@
 package com.inspur.smsb.gateway.filter;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.google.common.base.Strings;
+import com.inspur.smsb.gateway.dto.KeycloakUserDto;
+import com.inspur.smsb.gateway.utils.HttpClientUtil;
 import com.nimbusds.jose.JWSObject;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
 import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 过滤器,在请求头中解析 JWT 字段,并解析出 userId 回填
@@ -23,34 +31,102 @@ import java.text.ParseException;
 @Slf4j
 @Component
 public class WebFluxUserRequestInfoFilter implements GlobalFilter {
-
     @Autowired
     private AuthorizationClient authorizationClient;
+    @Value("${keycloak.auth-server-url}")
+    private String keyCloakServiceUrl;
+    @Value("${keycloak.realm}")
+    private String realm;
+    @Value("${keycloak.resource}")
+    private String clientId;
+    @Value("${keycloak.credentials.secret}")
+    private String clientSecret;
+    @Value("${keycloak.adminUserId}")
+    private String adminUserId;
 
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
-        try {
-            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
-            if (Strings.isNullOrEmpty(token)) {
-                return chain.filter(exchange);
-            }
-            String realToken = token.replace("Bearer ", "");
-            ServerHttpResponse response = exchange.getResponse();
-            if(authorizationClient.verifyToken(realToken)){
-                response.setStatusCode(HttpStatus.UNAUTHORIZED);
-                return response.setComplete();
+        String wxAppletId = exchange.getRequest().getHeaders().getFirst("WxAppletId");
+        if (!Strings.isNullOrEmpty(wxAppletId)) {
+            // search for userid
+            String tokenUrl = keyCloakServiceUrl + "realms/" + realm + "/protocol/openid-connect/token";
+            String token = getToken(tokenUrl, clientId, clientSecret);
+            if (StringUtils.hasText(token)) {
+                String url = keyCloakServiceUrl + "admin/realms/" + realm + "/users";
+                List<KeycloakUserDto> list = queryUsers(url, token);
+                list = list.stream().filter(keycloakUserDto -> {
+                    Map attributes = keycloakUserDto.getAttributes();
+                    if (attributes == null) {
+                        return false;
+                    }
+                    JSONArray array = (JSONArray) attributes.get("wechat-applet-openid");
+                    String openIdAttr = "";
+                    if (array != null && !array.isEmpty()) {
+                        openIdAttr = array.getString(0);
+                    }
+                    return StringUtils.hasText(openIdAttr) && openIdAttr.equals(wxAppletId);
+                }).collect(Collectors.toList());
+                if (!list.isEmpty()) {
+                    String userId = list.get(0).getId();
+
+                    ServerHttpRequest request = exchange.getRequest()
+                        .mutate()
+                        .header("userId", userId)
+                        .build();
+                    // 把新的 exchange 放回到过滤链
+                    return chain.filter(exchange.mutate().request(request).build());
+                }
             }
-            JWSObject jwsObject = JWSObject.parse(realToken);
-
-            ServerHttpRequest request = exchange.getRequest()
-                .mutate()
-                .header("userId", String.valueOf(jwsObject.getPayload().toJSONObject().get("sub")))
-                .build();
-            // 把新的 exchange 放回到过滤链
-            return chain.filter(exchange.mutate().request(request).build());
-        } catch (ParseException e) {
-            log.error(e.getMessage(), e);
             return chain.filter(exchange);
+        } else {
+            try {
+                String token = exchange.getRequest().getHeaders().getFirst("Authorization");
+                if (Strings.isNullOrEmpty(token)) {
+                    return chain.filter(exchange);
+                }
+                String realToken = token.replace("Bearer ", "");
+                JWSObject jwsObject = JWSObject.parse(realToken);
+
+                if (adminUserId.equals(String.valueOf(jwsObject.getPayload().toJSONObject().get("sub")))) {
+                    //just skip this adapter
+                    return chain.filter(exchange);
+                }
+
+                ServerHttpRequest request = exchange.getRequest()
+                    .mutate()
+                    .header("userId", String.valueOf(jwsObject.getPayload().toJSONObject().get("sub")))
+                    .build();
+                // 把新的 exchange 放回到过滤链
+                return chain.filter(exchange.mutate().request(request).build());
+            } catch (ParseException e) {
+                log.error(e.getMessage(), e);
+                return chain.filter(exchange);
+            }
+        }
+    }
+
+
+    public String getToken(String tokenUrl, String clientId, String clientSecret) {
+        try {
+            String content = "grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret;
+            log.info("tokenUrl:{},content:{}", tokenUrl, content);
+            Map<String, Object> result = HttpClientUtil.httpClientPost(tokenUrl, content, "content-type");
+            log.info("请求参数:" + result);
+            return (String) result.get("access_token");
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("获取token失败!{}", e.getMessage());
+            return null;
+        }
+    }
+
+    public List<KeycloakUserDto> queryUsers(String url, String token) {
+        String userMap = HttpClientUtil.sendGet(url, "Bearer " + token);
+        KeycloakUserDto[] result = JSONObject.parseObject(userMap, KeycloakUserDto[].class);
+        List<KeycloakUserDto> userList = new ArrayList<>();
+        for (KeycloakUserDto dto : result) {
+            userList.add(dto);
         }
+        return userList;
     }
 }

+ 141 - 0
src/main/java/com/inspur/smsb/gateway/utils/HttpClientUtil.java

@@ -0,0 +1,141 @@
+package com.inspur.smsb.gateway.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.*;
+import org.springframework.util.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * HTTP请求
+ *
+ * @author wangbo
+ * @since 2022/3/21
+ */
+@Slf4j
+public class HttpClientUtil {
+    /***
+     * httpClient-Get请求
+     * @param url 请求地址
+     * @return
+     * @throws Exception
+     */
+    public static String httpClientGet(String url) throws Exception {
+        HttpClient client = new HttpClient();
+        client.getParams().setContentCharset("UTF-8");
+        GetMethod httpGet = new GetMethod(url);
+        try {
+            client.executeMethod(httpGet);
+            String response = httpGet.getResponseBodyAsString();
+            // Map<String, Object> map = JSONObject.parseObject(response, Map.class);
+            return response;
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            httpGet.releaseConnection();
+        }
+    }
+
+    /***
+     * httpClient-Post请求
+     * @param url 请求地址
+     * @param params post参数
+     * @return
+     * @throws Exception
+     */
+    public static Map<String, Object> httpClientPost(String url, String params, String type) throws Exception {
+        HttpClient client = new HttpClient();
+        client.getParams().setContentCharset("UTF-8");
+
+        PostMethod httpPost = new PostMethod(url);
+        try {
+            RequestEntity requestEntity = new ByteArrayRequestEntity(params.getBytes("utf-8"));
+            httpPost.setRequestEntity(requestEntity);
+            if (StringUtils.hasText(type)) {
+                httpPost.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+            }
+            client.executeMethod(httpPost);
+            String response = httpPost.getResponseBodyAsString();
+            Map<String, Object> map = JSONObject.parseObject(response, Map.class);
+            return map;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            httpPost.releaseConnection();
+        }
+    }
+
+
+    public static String sendGet(String url, String authorization) {
+        String result = "";
+        BufferedReader in = null;
+        try {
+            URL realUrl = new URL(url);
+            // 打开和URL之间的连接
+            URLConnection connection = realUrl.openConnection();
+            // 设置通用的请求属性
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent",
+                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            connection.setRequestProperty("Authorization", authorization);
+            // 建立实际的连接
+            connection.connect();
+            // 获取所有响应头字段
+            Map<String, List<String>> map = connection.getHeaderFields();
+            // 遍历所有的响应头字段
+            for (String key : map.keySet()) {
+                System.out.println(key + "--->" + map.get(key));
+            }
+            // 定义 BufferedReader输入流来读取URL的响应
+            in = new BufferedReader(new InputStreamReader(
+                connection.getInputStream()));
+            String line;
+            while ((line = in.readLine()) != null) {
+                result += line;
+            }
+        } catch (Exception e) {
+            System.out.println("发送GET请求出现异常!" + e);
+            e.printStackTrace();
+        }
+        // 使用finally块来关闭输入流
+        finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (Exception e2) {
+                e2.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+
+    public static String doPut(String strUrl, String param, String token) {
+        HttpClient client = new HttpClient();
+        String strReturn = "";
+        PutMethod httpput = new PutMethod(strUrl);
+        httpput.setRequestHeader("Authorization", "Bearer " + token);
+        try {
+            if (param != null) {
+                RequestEntity entity = new StringRequestEntity(param, "application/json", "UTF-8");
+                httpput.setRequestEntity(entity);
+            }
+            client.executeMethod(httpput);
+            byte[] bytes = httpput.getResponseBody();
+            strReturn = new String(bytes);
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return strReturn;
+    }
+}

+ 1 - 3
src/main/resources/bootstrap.yml

@@ -1,6 +1,3 @@
-server:
-  port: 8081
-
 spring:
   application:
     name: smsb-gateway
@@ -12,3 +9,4 @@ spring:
       config:
         file-extension: yml
         refresh-enabled: true
+