Quellcode durchsuchen

增加用户行为日志

leon vor 4 Jahren
Ursprung
Commit
b468aceec6

+ 12 - 0
pom.xml

@@ -175,6 +175,18 @@
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- High-level-Rest-Client-->
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+            <version>6.4.3</version>
+        </dependency>
+        <!-- es 依赖 -->
+        <dependency>
+            <groupId>org.elasticsearch</groupId>
+            <artifactId>elasticsearch</artifactId>
+            <version>6.4.3</version>
+        </dependency>
     </dependencies>
     <profiles>
         <!--        <profile>-->

+ 45 - 0
src/main/java/com/mokamrp/privates/config/EsConfig.java

@@ -0,0 +1,45 @@
+package com.mokamrp.privates.config;
+
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * ElasticSearch Rest Client config
+ **/
+@Configuration
+public class EsConfig {
+
+    @Bean
+    public RestHighLevelClient restHighLevelClient(
+            @Value("${es.host}") String host,
+            @Value("${es.port}") Integer port,
+            @Value("${es.username}") String username,
+            @Value("${es.password}") String password
+    ) {
+        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
+        return new RestHighLevelClient(
+                RestClient.builder(
+                        new HttpHost(host, port, "http")
+                )
+                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
+                    @Override
+                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
+                        httpClientBuilder.disableAuthCaching();
+                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+                    }
+                }));
+
+    }
+}

+ 38 - 0
src/main/java/com/mokamrp/privates/config/FilterConfig.java

@@ -0,0 +1,38 @@
+package com.mokamrp.privates.config;
+
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+@Configuration
+@Order(-1)
+public class FilterConfig implements Filter {
+
+    @Override
+    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        ServletRequest requestWrapper = null;
+        if(servletRequest instanceof HttpServletRequest) {
+            requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
+        }
+        if(requestWrapper == null) {
+            filterChain.doFilter(servletRequest, servletResponse);
+        } else {
+            filterChain.doFilter(requestWrapper, servletResponse);
+        }
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

+ 103 - 0
src/main/java/com/mokamrp/privates/config/RequestWrapper.java

@@ -0,0 +1,103 @@
+package com.mokamrp.privates.config;
+
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.*;
+import java.nio.charset.Charset;
+
+/**
+ * 保存过滤器里面的流
+ */
+public class RequestWrapper extends HttpServletRequestWrapper {
+
+    private final byte[] body;
+
+    public RequestWrapper(HttpServletRequest request) {
+        super(request);
+        String sessionStream = getBodyString(request);
+        body = sessionStream.getBytes(Charset.forName("UTF-8"));
+    }
+
+    /**
+     * 获取请求Body
+     *
+     * @param request
+     * @return
+     */
+    public String getBodyString(final ServletRequest request) {
+        StringBuilder sb = new StringBuilder();
+        try (InputStream inputStream = cloneInputStream(request.getInputStream());
+             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Description: 复制输入流</br>
+     *
+     * @param inputStream
+     * @return</br>
+     */
+    public InputStream cloneInputStream(ServletInputStream inputStream) {
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int len;
+        try {
+            while ((len = inputStream.read(buffer)) > -1) {
+                byteArrayOutputStream.write(buffer, 0, len);
+            }
+            byteArrayOutputStream.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+    }
+
+    @Override
+    public BufferedReader getReader() {
+
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() {
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+        return new ServletInputStream() {
+
+            @Override
+            public int read() {
+
+                return bais.read();
+            }
+
+            @Override
+            public boolean isFinished() {
+
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+
+            }
+        };
+    }
+}

+ 6 - 0
src/main/java/com/mokamrp/privates/constant/ESKey.java

@@ -0,0 +1,6 @@
+package com.mokamrp.privates.constant;
+
+public class ESKey {
+    //.私域后台 用户行为日志
+    public static final String MokaPrivateUrlLog = "-moka-private-url-log-";
+}

+ 58 - 8
src/main/java/com/mokamrp/privates/interceptor/AuthIntercepotor.java

@@ -1,19 +1,36 @@
 package com.mokamrp.privates.interceptor;
 
+import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.mokamrp.privates.cache.RedisCache;
+import com.mokamrp.privates.config.RequestWrapper;
+import com.mokamrp.privates.constant.ESKey;
 import com.mokamrp.privates.mapper.pojo.User;
 import com.mokamrp.privates.service.UserService;
+import com.mokamrp.privates.utils.http.HttpRequestTools;
 import com.xxl.sso.core.conf.Conf;
 import com.xxl.sso.core.user.XxlSsoUser;
+import org.apache.poi.util.SystemOutLogger;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.xcontent.XContentType;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.SortedMap;
 
 /**
  * @author leon token认证
@@ -32,6 +49,13 @@ public class AuthIntercepotor extends HandlerInterceptorAdapter {
     @Value("${xxl-sso.excluded.paths}")
     private String xxlSsoExcludedPaths;
 
+    @Value("${spring.profiles.active}")
+    private String env;
+
+    @Autowired
+    @Qualifier(value = "restHighLevelClient")
+    private RestHighLevelClient esClient;
+
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         //.跨域
@@ -48,14 +72,6 @@ public class AuthIntercepotor extends HandlerInterceptorAdapter {
                 return true;
             }
         }
-//        if (requestUrl.equals("/private/healthy")) {
-//            return true;
-//        }
-//
-//        if (requestUrl.equals("/mochat/weWork/callback")) {
-//            return true;
-//        }
-
         XxlSsoUser xxlSsoUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
         Map<String, String> plugininfo = xxlSsoUser.getPlugininfo();
         User user = new User();
@@ -79,6 +95,40 @@ public class AuthIntercepotor extends HandlerInterceptorAdapter {
         }
         request.setAttribute("auth-user", user);
         userService.Insert(xxlSsoUser.getPlugininfo(), xxlSsoUser.getUsername());
+        this.setlog(user.getName(),user.getUserId(),requestUrl,request);
         return true;
     }
+
+    //.@leon 用户操作日志
+    public Boolean setlog(String userNm,String userId,String url,HttpServletRequest request){
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy.MM.dd");
+        String dateTimeStr = LocalDateTime.now().toString();
+        String dateStr = LocalDate.now().format(dtf);
+        Long timestamp = System.currentTimeMillis()/1000;
+        try {
+            Map<String,Object> log = new HashMap<>();
+            SortedMap<String, String> param = HttpRequestTools.getAllParams(request);
+            log.put("param",param);
+            log.put("url", url);
+            log.put("userNm", userNm);
+            log.put("userId", userId);
+            log.put("datetime",dateTimeStr);
+            log.put("timestamp",timestamp);
+            String paramStr = JSON.toJSONString(log);
+            // 3.创建请求对象,指定索引库、类型、id(可选)
+            IndexRequest indexRequest = new IndexRequest(env + ESKey.MokaPrivateUrlLog + dateStr, "requestBody");
+            // 4.调用source方法将请求数据封装到IndexRequest请求对象中
+            indexRequest.source(paramStr, XContentType.JSON);
+            try {
+                // 5.调用方法进行数据通信
+                IndexResponse indexResponse = esClient.index(indexRequest, RequestOptions.DEFAULT);
+                return true;
+            } catch (IOException e) {
+                e.printStackTrace();
+                return false;
+            }
+        } catch (IOException e1){
+            return false;
+        }
+    }
 }

+ 113 - 0
src/main/java/com/mokamrp/privates/utils/http/HttpRequestTools.java

@@ -0,0 +1,113 @@
+package com.mokamrp.privates.utils.http;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson.parser.Feature;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * http 工具类 获取请求中的参数
+ */
+@Slf4j
+public class HttpRequestTools {
+    /**
+     * 读取请求的 Body
+     *
+     * @param request
+     * @return
+     * @throws IOException
+     */
+    public static String getBody(HttpServletRequest request) throws IOException {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
+        String str;
+        StringBuilder wholeStr = new StringBuilder();
+        // 一行一行的读取body体里面的内容;
+        while ((str = reader.readLine()) != null) {
+            wholeStr.append(str);
+        }
+        wholeStr.trimToSize();
+        return wholeStr.toString();
+    }
+
+    /**
+     * 将URL的参数和body参数合并
+     *
+     * @param request
+     */
+    public static SortedMap<String, String> getAllParams(HttpServletRequest request) throws IOException {
+        SortedMap<String, String> result = new TreeMap<>();
+        // 获取URL上的参数
+        getUrlParams(request, result);
+        // 获取body参数
+        getAllRequestParam(request, result);
+        return result;
+    }
+
+    /**
+     * 获取 Body 参数
+     *
+     * @param request
+     */
+    public static void getAllRequestParam(final HttpServletRequest request, SortedMap<String, String> result)
+            throws IOException {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
+        String str = "";
+        StringBuilder wholeStr = new StringBuilder();
+        // 一行一行的读取body体里面的内容;
+        while ((str = reader.readLine()) != null) {
+            wholeStr.append(str);
+        }
+        wholeStr.trimToSize();
+        String s = wholeStr.toString();
+        log.debug("request body : {}", s);
+        if (!StringUtils.isEmpty(s)) {
+            try {
+                // 转化成json对象
+                Map<String, String> allRequestParam = JSONObject.parseObject(s, new TypeReference<Map<String, String>>() {
+                }, Feature.OrderedField);
+                // 将URL的参数和body参数进行合并
+                for (Map.Entry entry : allRequestParam.entrySet()) {
+                    result.put((String) entry.getKey(), (String) entry.getValue());
+                }
+            } catch (Exception e) {
+                log.error("getAllRequestParam error: {} (入参:{})", e.getMessage(), s);
+            }
+        }
+    }
+
+    /**
+     * 获取url参数
+     *
+     * @param request
+     */
+    public static void getUrlParams(HttpServletRequest request, SortedMap<String, String> result) {
+        String param = "";
+        try {
+            String urlParam = request.getQueryString();
+            if (urlParam != null) {
+                param = URLDecoder.decode(urlParam, "utf-8");
+            }
+            log.debug("request url param : {}", param);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        String[] params = param.split("&");
+        for (String s : params) {
+            int index = s.indexOf("=");
+            if (index != -1) {
+                result.put(s.substring(0, index), s.substring(index + 1));
+            }
+        }
+    }
+}

+ 5 - 0
src/main/resources/application-local.properties

@@ -75,5 +75,10 @@ datahub.topic=s_hera_api_external_user
 datahub.corpTopic=ods_hera_msv_corp_data
 datahub.project=hera
 
+es.host=es-cn-4591gc2fx0001549q.public.elasticsearch.aliyuncs.com
+es.username=elastic
+es.password=moka6_3moka
+es.port=9200
+
 #定时任务全局开关,本地环境无需开启
 cronjob.power=true

+ 5 - 0
src/main/resources/application-prod.properties

@@ -69,5 +69,10 @@ datahub.topic=s_hera_api_external_user
 datahub.corpTopic=ods_hera_msv_corp_data
 datahub.project=hera
 
+es.host=es-cn-4591gc2fx0001549q.public.elasticsearch.aliyuncs.com
+es.username=elastic
+es.password=moka6_3moka
+es.port=9200
+
 #定时任务全局开关,线上环境需要开启
 cronjob.power=true

+ 6 - 0
src/main/resources/application-test.properties

@@ -69,6 +69,12 @@ datahub.accessSecret=p9tVmeDeeEENKhfsBsSeYc0F0ggH5b
 datahub.topic=s_hera_api_external_user_test
 datahub.corpTopic=ods_hera_msv_corp_data
 datahub.project=hera
+
+es.host=es-cn-4591gc2fx0001549q.public.elasticsearch.aliyuncs.com
+es.username=elastic
+es.password=moka6_3moka
+es.port=9200
+
 #定时任务全局开关,线上环境需要开启
 cronjob.power=false