浏览代码

日志aop

chengyao 3 年之前
父节点
当前提交
e34747b0ed
共有 22 个文件被更改,包括 1116 次插入23 次删除
  1. 97 0
      common/src/main/java/com/lantone/common/dto/AbnormalLogDTO.java
  2. 100 0
      common/src/main/java/com/lantone/common/dto/LoginLogDTO.java
  3. 107 0
      common/src/main/java/com/lantone/common/dto/OperationLogDTO.java
  4. 46 0
      common/src/main/java/com/lantone/common/util/AddressUtils.java
  5. 86 1
      common/src/main/java/com/lantone/common/util/HttpUtils.java
  6. 165 0
      common/src/main/java/com/lantone/common/util/IpUtils.java
  7. 54 3
      dblayer-mbg/src/main/java/com/lantone/dblayermbg/entity/AbnormalLog.java
  8. 4 1
      dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/AbnormalLogMapper.java
  9. 4 1
      dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/LoginLogMapper.java
  10. 4 1
      dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/OperationLogMapper.java
  11. 4 1
      dblayer-mbg/src/main/resources/mapper/AbnormalLogMapper.xml
  12. 4 1
      dblayer-mbg/src/main/resources/mapper/LoginLogMapper.xml
  13. 4 1
      dblayer-mbg/src/main/resources/mapper/OperationLogMapper.xml
  14. 9 0
      dblayer-mbg/src/main/resources/mapper/base/BaseAbnormalLogMapper.xml
  15. 8 0
      pom.xml
  16. 5 0
      security-center/pom.xml
  17. 183 0
      security-center/src/main/java/com/lantone/security/aop/LogAspect.java
  18. 35 0
      security-center/src/main/java/com/lantone/security/component/MessageReceiver.java
  19. 41 0
      security-center/src/main/java/com/lantone/security/component/MessageSender.java
  20. 81 0
      security-center/src/main/java/com/lantone/security/config/RabbitMqConfig.java
  21. 16 1
      security-center/src/main/java/com/lantone/security/enums/QueueEnum.java
  22. 59 12
      security-center/src/main/java/com/lantone/security/facade/UserManagementFacade.java

+ 97 - 0
common/src/main/java/com/lantone/common/dto/AbnormalLogDTO.java

@@ -0,0 +1,97 @@
+
+package com.lantone.common.dto;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description:
+ * @Author: cy
+ * @time: 2021/9/5 16:55
+ */
+@Data
+public class AbnormalLogDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 操作人用户ID
+     */
+    private Long operationId;
+
+    /**
+     * 操作人用户名
+     */
+    private String operationName;
+
+    /**
+     * 操作请求方式
+     */
+    private String operationWay;
+
+    /**
+     * 操作请求方法
+     */
+    private String operationMethod;
+
+    /**
+     * 操作url
+     */
+    private String operationUrl;
+
+    /**
+     * 操作参数
+     */
+    private String operationParam;
+
+    /**
+     * ip地址
+     */
+    private String operationIp;
+
+    /**
+     * 代理ip地址
+     */
+    private String operationAgent;
+
+    /**
+     * 操作异常信息
+     */
+    private String operationErrorInfo;
+
+    /**
+     * 是否删除,N:未删除,Y:删除
+     */
+    private String isDeleted;
+
+    /**
+     * 记录创建时间
+     */
+    private Date gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    private Date gmtModified;
+
+    /**
+     * 创建人,0表示无创建人值
+     */
+    private String creator;
+
+    /**
+     * 修改人,如果为0则表示纪录未修改
+     */
+    private String modifier;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 100 - 0
common/src/main/java/com/lantone/common/dto/LoginLogDTO.java

@@ -0,0 +1,100 @@
+
+
+package com.lantone.common.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description:
+ * @Author: cy
+ * @time: 2021/9/5 16:56
+ */
+@Data
+public class LoginLogDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 登录用户ID
+     */
+    @TableField("login_id")
+    private Long loginId;
+
+    /**
+     * 登录用户名
+     */
+    @TableField("login_name")
+    private String loginName;
+
+    /**
+     * 登录日期
+     */
+    @TableField("login_date")
+    private Date loginDate;
+
+    /**
+     * 登录ip
+     */
+    @TableField("login_ip")
+    private String loginIp;
+
+    /**
+     * 登录ip地址
+     */
+    @TableField("login_address")
+    private String loginAddress;
+
+    /**
+     * 浏览器
+     */
+    @TableField("login_browser")
+    private String loginBrowser;
+
+    /**
+     * 是否删除,N:未删除,Y:删除
+     */
+    @TableField("is_deleted")
+    private String isDeleted;
+
+    /**
+     * 记录创建时间
+     */
+    @TableField("gmt_create")
+    private Date gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    @TableField("gmt_modified")
+    private Date gmtModified;
+
+    /**
+     * 创建人,0表示无创建人值
+     */
+    @TableField("creator")
+    private String creator;
+
+    /**
+     * 修改人,如果为0则表示纪录未修改
+     */
+    @TableField("modifier")
+    private String modifier;
+
+    /**
+     * 备注
+     */
+    @TableField("remark")
+    private String remark;
+
+}

+ 107 - 0
common/src/main/java/com/lantone/common/dto/OperationLogDTO.java

@@ -0,0 +1,107 @@
+package com.lantone.common.dto;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description:
+ * @Author: cy
+ * @time: 2021/9/5 16:56
+ */
+
+@Data
+public class OperationLogDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 操作人用户ID
+     */
+    private Long operationId;
+
+    /**
+     * 操作人用户名
+     */
+    private String operationName;
+
+    /**
+     * 操作日期
+     */
+    private Date operationDate;
+
+    /**
+     * 操作记录
+     */
+    private String operationRecord;
+
+    /**
+     * ip地址
+     */
+    private String operationIp;
+
+    /**
+     * 操作地址
+     */
+    private String operationAddress;
+
+    /**
+     * 操作方法
+     */
+    private String operationMethod;
+
+    /**
+     * 操作请求方式
+     */
+    private String operationWay;
+
+    /**
+     * 操作url
+     */
+    private String operationUrl;
+
+    /**
+     * 操作参数
+     */
+    private String operationParam;
+
+    /**
+     * 返回参数
+     */
+    private String jsonResult;
+
+    /**
+     * 是否删除,N:未删除,Y:删除
+     */
+    private String isDeleted;
+
+    /**
+     * 记录创建时间
+     */
+    private Date gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    private Date gmtModified;
+
+    /**
+     * 创建人,0表示无创建人值
+     */
+    private String creator;
+
+    /**
+     * 修改人,如果为0则表示纪录未修改
+     */
+    private String modifier;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 46 - 0
common/src/main/java/com/lantone/common/util/AddressUtils.java

@@ -0,0 +1,46 @@
+package com.lantone.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @Description:获取地址类
+ * @Author: cy
+ * @time: 2021/9/5 16:59
+ */
+
+public class AddressUtils {
+    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+    // IP地址查询
+    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+    // 未知地址
+    public static final String UNKNOWN = "未知地址";
+
+    public static String getRealAddressByIP(String ip) {
+        String address = UNKNOWN;
+        // 内网不查询
+        if (IpUtils.internalIp(ip)) {
+            return "内网IP";
+        }
+        try {
+            String rspStr = HttpUtils.sendPost(IP_URL, "ip=" + ip + "&json=true");
+            if (StringUtil.isNotBlank(rspStr)) {
+                log.error("获取地理位置异常 {}", ip);
+                return UNKNOWN;
+            }
+            JSONObject obj = JSONObject.parseObject(rspStr);
+            String region = obj.getString("pro");
+            String city = obj.getString("city");
+            return String.format("%s %s", region, city);
+        } catch (Exception e) {
+            log.error("获取地理位置异常 {}", e);
+        }
+
+        return address;
+    }
+}
+
+

+ 86 - 1
common/src/main/java/com/lantone/common/util/HttpUtils.java

@@ -1,9 +1,19 @@
 package com.lantone.common.util;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -15,6 +25,8 @@ import java.util.Map;
  */
 public class HttpUtils {
 
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
     /**
      * 获取当前请求的HttpServletRequest实例
      *
@@ -108,7 +120,80 @@ public class HttpUtils {
                 }
             }
         }
-        return ip;
+        return  "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+    }
+
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendPost(String url, String param)
+    {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            String urlNameString = url;
+            log.info("sendPost - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.print(param);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
     }
 
 }

+ 165 - 0
common/src/main/java/com/lantone/common/util/IpUtils.java

@@ -0,0 +1,165 @@
+package com.lantone.common.util;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @Description:获取IP方法
+ * @Author: cy
+ * @time: 2021/9/5 17:00
+ */
+
+public class IpUtils {
+    public static String getIpAddr(HttpServletRequest request) {
+        if (request == null) {
+            return "unknown";
+        }
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Real-IP");
+        }
+
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+    }
+
+    public static boolean internalIp(String ip) {
+        byte[] addr = textToNumericFormatV4(ip);
+        return internalIp(addr) || "127.0.0.1".equals(ip);
+    }
+
+    private static boolean internalIp(byte[] addr) {
+        if (null == addr || addr.length < 2) {
+            return true;
+        }
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        switch (b0) {
+            case SECTION_1:
+                return true;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
+                    return true;
+                }
+            case SECTION_5:
+                switch (b1) {
+                    case SECTION_6:
+                        return true;
+                }
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * 将IPv4地址转换成字节
+     *
+     * @param text IPv4地址
+     * @return byte 字节
+     */
+    public static byte[] textToNumericFormatV4(String text) {
+        if (text.length() == 0) {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try {
+            long l;
+            int i;
+            switch (elements.length) {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L)) {
+                        return null;
+                    }
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i) {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L)) {
+                        return null;
+                    }
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i) {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        } catch (NumberFormatException e) {
+            return null;
+        }
+        return bytes;
+    }
+
+    public static String getHostIp() {
+        try {
+            return InetAddress.getLocalHost().getHostAddress();
+        } catch (UnknownHostException e) {
+        }
+        return "127.0.0.1";
+    }
+
+    public static String getHostName() {
+        try {
+            return InetAddress.getLocalHost().getHostName();
+        } catch (UnknownHostException e) {
+        }
+        return "未知";
+    }
+}

+ 54 - 3
dblayer-mbg/src/main/java/com/lantone/dblayermbg/entity/AbnormalLog.java

@@ -5,9 +5,6 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
 import java.io.Serializable;
 import java.util.Date;
 
@@ -28,6 +25,60 @@ public class AbnormalLog implements Serializable {
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
+    /**
+     * 操作人用户ID
+     */
+    @TableField("operation_id")
+    private Long operationId;
+
+    /**
+     * 操作人用户名
+     */
+    @TableField("operation_name")
+    private String operationName;
+
+    /**
+     * 操作方法
+     */
+    @TableField("operation_method")
+    private String operationMethod;
+
+    /**
+     * 操作请求方式
+     */
+    @TableField("operation_way")
+    private String operationWay;
+
+    /**
+     * 操作url
+     */
+    @TableField("operation_url")
+    private String operationUrl;
+
+    /**
+     * 操作参数
+     */
+    @TableField("operation_param")
+    private String operationParam;
+
+    /**
+     * ip地址
+     */
+    @TableField("operation_ip")
+    private Integer operationIp;
+
+    /**
+     * 代理ip地址
+     */
+    @TableField("operation_agent")
+    private Integer operationAgent;
+
+    /**
+     * 操作异常信息
+     */
+    @TableField("operation_error_info")
+    private String operationErrorInfo;
+
     /**
      * 是否删除,N:未删除,Y:删除
      */

+ 4 - 1
dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/AbnormalLogMapper.java

@@ -1,13 +1,16 @@
 package com.lantone.dblayermbg.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lantone.common.dto.AbnormalLogDTO;
 import com.lantone.dblayermbg.entity.AbnormalLog;
+import org.springframework.stereotype.Repository;
 
 /**
  * <p>
  * 表名:sys_abnormal_log Mapper接口
  * </p>
  */
+@Repository
 public interface AbnormalLogMapper extends BaseMapper<AbnormalLog> {
-
+    void addOperErrorLog(AbnormalLogDTO abnormalLogDTO);
 }

+ 4 - 1
dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/LoginLogMapper.java

@@ -1,13 +1,16 @@
 package com.lantone.dblayermbg.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lantone.common.dto.LoginLogDTO;
 import com.lantone.dblayermbg.entity.LoginLog;
+import org.springframework.stereotype.Repository;
 
 /**
  * <p>
  * 表名:sys_login_log Mapper接口
  * </p>
  */
+@Repository
 public interface LoginLogMapper extends BaseMapper<LoginLog> {
-
+    void addLoginLog(LoginLogDTO loginLogDTO);
 }

+ 4 - 1
dblayer-mbg/src/main/java/com/lantone/dblayermbg/mapper/OperationLogMapper.java

@@ -1,13 +1,16 @@
 package com.lantone.dblayermbg.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.lantone.common.dto.OperationLogDTO;
 import com.lantone.dblayermbg.entity.OperationLog;
+import org.springframework.stereotype.Repository;
 
 /**
  * <p>
  * 表名:sys_operation_log Mapper接口
  * </p>
  */
+@Repository
 public interface OperationLogMapper extends BaseMapper<OperationLog> {
-
+    void addOperLog(OperationLogDTO operationLog);
 }

+ 4 - 1
dblayer-mbg/src/main/resources/mapper/AbnormalLogMapper.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.lantone.dblayermbg.mapper.AbnormalLogMapper">
-
+    <insert id="addOperErrorLog">
+    insert into sys_abnormal_log(operation_id,operation_name,operation_ip,operation_agent,operation_error_info,operation_method,operation_way,operation_url,operation_param,gmt_create)
+    values (#{operationId},#{operationName},INET_ATON(#{operationIp}),INET_ATON(#{operationAgent}),#{operationErrorInfo},#{operationMethod},#{operationWay},#{operationUrl},#{operationParam},#{gmtCreate})
+    </insert>
 </mapper>

+ 4 - 1
dblayer-mbg/src/main/resources/mapper/LoginLogMapper.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.lantone.dblayermbg.mapper.LoginLogMapper">
-
+    <insert id="addLoginLog">
+    insert into sys_login_log(login_id,login_name,login_date,login_ip,login_address,login_browser,gmt_create)
+    values (#{loginId},#{loginName},#{loginDate},INET_ATON(#{loginIp}),#{loginAddress},#{loginBrowser},#{gmtCreate})
+    </insert>
 </mapper>

+ 4 - 1
dblayer-mbg/src/main/resources/mapper/OperationLogMapper.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.lantone.dblayermbg.mapper.OperationLogMapper">
-
+    <insert id="addOperLog">
+    insert into sys_operation_log(operation_id,operation_name,operation_date,operation_ip,operation_address,operation_method,operation_way,operation_url,operation_param,json_result,gmt_create)
+    values (#{operationId},#{operationName},#{operationDate},INET_ATON(#{operationIp}),#{operationAddress},#{operationMethod},#{operationWay},#{operationUrl},#{operationParam},#{jsonResult},#{gmtCreate})
+    </insert>
 </mapper>

+ 9 - 0
dblayer-mbg/src/main/resources/mapper/base/BaseAbnormalLogMapper.xml

@@ -5,6 +5,15 @@
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.lantone.dblayermbg.entity.AbnormalLog">
         <id column="id" property="id"/>
+        <result column="operation_id" property="operationId"/>
+        <result column="operation_name" property="operationName"/>
+        <result column="operation_method" property="operationMethod"/>
+        <result column="operation_way" property="operationWay"/>
+        <result column="operation_url" property="operationUrl"/>
+        <result column="operation_param" property="operationParam"/>
+        <result column="operation_ip" property="operationIp"/>
+        <result column="operation_agent" property="operationAgent"/>
+        <result column="operation_error_info" property="operationErrorInfo"/>
         <result column="is_deleted" property="isDeleted"/>
         <result column="gmt_create" property="gmtCreate"/>
         <result column="gmt_modified" property="gmtModified"/>

+ 8 - 0
pom.xml

@@ -42,6 +42,7 @@
         <beetl.version>3.0.13.RELEASE</beetl.version>
         <lombok.version>1.18.8</lombok.version>
         <guava.version>28.1-jre</guava.version>
+        <bitwalker.version>1.21</bitwalker.version>
         <hutool-all.version>5.4.0</hutool-all.version>
         <knife4j-micro-spring-boot-starter.version>2.0.4</knife4j-micro-spring-boot-starter.version>
         <commons-lang3.version>3.8.1</commons-lang3.version>
@@ -209,6 +210,13 @@
                 <version>${commons-codec.version}</version>
             </dependency>
 
+            <!-- 解析客户端操作系统、浏览器等 -->
+            <dependency>
+                <groupId>eu.bitwalker</groupId>
+                <artifactId>UserAgentUtils</artifactId>
+                <version>${bitwalker.version}</version>
+            </dependency>
+
             <!-- poi excel -->
             <dependency>
                 <groupId>org.apache.poi</groupId>

+ 5 - 0
security-center/pom.xml

@@ -18,6 +18,11 @@
             <groupId>com.lantone</groupId>
             <artifactId>dblayer-mbg</artifactId>
         </dependency>
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

+ 183 - 0
security-center/src/main/java/com/lantone/security/aop/LogAspect.java

@@ -0,0 +1,183 @@
+package com.lantone.security.aop;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.lantone.common.dto.AbnormalLogDTO;
+import com.lantone.common.dto.OperationLogDTO;
+import com.lantone.common.util.HttpUtils;
+import com.lantone.common.util.SysUserUtils;
+import com.lantone.security.component.MessageSender;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.util.Date;
+import java.util.Map;
+/**
+ * @Description:日志记录处理
+ * @Author: cy
+ * @time: 2021/9/5 17:18
+ */
+
+@Aspect
+@Component
+public class LogAspect {
+    @Autowired
+    private MessageSender messageSender;
+
+    // 操作配置织入点
+    @Pointcut("execution(public * com.lantone.security.web.RegionManagementController.*(..))")
+    public void operPointCut() {
+    }
+
+    // 异常配置织入点
+    @Pointcut("execution(public * com.lantone.security.web.*.*(..))")
+    public void errorPointCut() {
+    }
+
+    /**
+     * 拦截异常操作
+     *
+     * @param joinPoint 切点
+     * @param e         异常
+     */
+    @AfterThrowing(value = "errorPointCut()", throwing = "e")
+    public void errorAfterThrowing(JoinPoint joinPoint, Exception e) {
+        errorLog(joinPoint, e);
+    }
+
+    /**
+     * 操作后执行
+     *
+     * @param
+     */
+    @AfterReturning(pointcut = "operPointCut()", returning = "jsonResult")
+    public void operAfterReturning(JoinPoint joinPoint, Object jsonResult) {
+        operLog(joinPoint, jsonResult);
+    }
+
+    /**
+     * @Description: 操作日志记录
+     * @Param: [joinPoint, jsonResult]
+     * @return: void
+     * @Author: cy
+     * @Date: 2021/9/2
+     */
+    protected void operLog(JoinPoint joinPoint, Object jsonResult) {
+        OperationLogDTO operationLog = multiplexing(joinPoint);
+        // 返回参数
+        if (null != jsonResult) {
+            ObjectMapper objectWriter = new ObjectMapper();
+            try {
+                operationLog.setJsonResult(StringUtils.substring(objectWriter.writeValueAsString(jsonResult), 0, 1000));
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+            }
+        }
+        messageSender.sendOperLogRecordMessage(operationLog);
+    }
+
+
+    /**
+     * @Description: 异常日志记录
+     * @Param: [joinPoint, jsonResult]
+     * @return: void
+     * @Author: cy
+     * @Date: 2021/9/2
+     */
+    protected void errorLog(JoinPoint joinPoint, Exception e) {
+        AbnormalLogDTO abnormalLogDTO = new AbnormalLogDTO();
+        OperationLogDTO operationLog = multiplexing(joinPoint);
+        BeanUtils.copyProperties(operationLog,abnormalLogDTO);
+        abnormalLogDTO.setOperationErrorInfo(StringUtils.substring(e.toString(), 0, 1000));
+        messageSender.operErrorLogRecordMessage(abnormalLogDTO);
+    }
+
+    /**
+     * @Description: 返回信息相同日志代码复用
+     * @Param: [joinPoint]
+     * @return: com.lantone.common.dto.OperationLogDTO
+     * @Author: cy
+     * @Date: 2021/9/5
+     */
+    public OperationLogDTO multiplexing(JoinPoint joinPoint){
+        OperationLogDTO operationLog = new OperationLogDTO();
+        Date date = new Date();
+        operationLog.setOperationDate(date);
+        operationLog.setGmtCreate(date);
+        operationLog.setOperationId(SysUserUtils.getCurrentPrincipleId());
+        operationLog.setOperationName(SysUserUtils.getCurrentPrinciple());
+        operationLog.setOperationIp(HttpUtils.getIpAddress());
+        // 设置方法名称
+        String className = joinPoint.getTarget().getClass().getName();
+        String methodName = joinPoint.getSignature().getName();
+        operationLog.setOperationMethod(className + "." + methodName + "()");
+        // 设置请求方式
+        operationLog.setOperationWay(HttpUtils.getHttpServletRequest().getMethod());
+        operationLog.setOperationUrl(HttpUtils.getHttpServletRequest().getRequestURI());
+        // 处理设置注解上的参数
+        try {
+            String params = getControllerMethodDescription(joinPoint);
+            if (StringUtils.isNotBlank(params)) {
+                operationLog.setOperationParam(params);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return operationLog;
+    }
+
+    /**
+     * @Description:获取请求的参数
+     * @Param: [joinPoint, logInformation]
+     * @return: void
+     * @Author: cy
+     * @Date: 2021/9/2
+     */
+    private String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
+        Map<String, String[]> map = HttpUtils.getHttpServletRequest().getParameterMap();
+        if (MapUtils.isNotEmpty(map)) {
+            String params = JSONObject.toJSONString(map);
+            return params;
+        } else {
+            Object args = joinPoint.getArgs();
+            if (null != args) {
+                String params = argsArrayToString(joinPoint.getArgs());
+                return StringUtils.substring(params, 0, 1000);
+            }
+        }
+        return "";
+    }
+
+
+    /**
+     * 参数拼装
+     *
+     * @Description:
+     * @Param: [paramsArray]
+     * @return: java.lang.String
+     * @Author: cy
+     * @Date: 2021/9/2
+     */
+    private String argsArrayToString(Object[] paramsArray) {
+        String params = "";
+        if (paramsArray != null && paramsArray.length > 0) {
+            for (int i = 0; i < paramsArray.length; i++) {
+                if (null != (paramsArray[i])) {
+                    Object jsonObj = JSONObject.toJSONString(paramsArray[i]);
+                    params += jsonObj.toString() + " ";
+                }
+            }
+        }
+        return params.trim();
+    }
+}
+
+

+ 35 - 0
security-center/src/main/java/com/lantone/security/component/MessageReceiver.java

@@ -1,5 +1,12 @@
 package com.lantone.security.component;
 
+import com.lantone.common.dto.AbnormalLogDTO;
+import com.lantone.common.dto.OperationLogDTO;
+import com.lantone.dblayermbg.mapper.AbnormalLogMapper;
+import com.lantone.dblayermbg.mapper.LoginLogMapper;
+import com.lantone.dblayermbg.mapper.OperationLogMapper;
+import com.lantone.common.dto.LoginLogDTO;
+import com.lantone.common.util.AddressUtils;
 import com.lantone.dblayermbg.facade.DictionaryInfoFacade;
 import com.lantone.dblayermbg.facade.HospitalSetFacade;
 import com.lantone.dblayermbg.facade.ResourceFacade;
@@ -28,6 +35,13 @@ public class MessageReceiver {
     private HospitalSetFacade hospitalSetFacade;
     @Autowired
     private ResourceFacade resourceFacade;
+    @Autowired
+    private LoginLogMapper loginLogMapper;
+    @Autowired
+    private OperationLogMapper operationLogMapper;
+    @Autowired
+    private AbnormalLogMapper abnormalLogMapper;
+
 
     @RabbitListener(queues = "emrais.redis.cache.refresh.queue", ackMode = "MANUAL")
     public void RedisCacheRefreshHandle(String type, Message message, Channel channel) throws Exception {
@@ -41,4 +55,25 @@ public class MessageReceiver {
         channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
     }
 
+    @RabbitListener(queues = "emrais.login.success.record.queue", ackMode = "MANUAL")
+    public void sendLogSuccessMessageHandle(LoginLogDTO loginLog, Message message, Channel channel) throws Exception {
+        loginLog.setLoginAddress(AddressUtils.getRealAddressByIP(loginLog.getLoginIp()));
+        loginLogMapper.addLoginLog(loginLog);
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+    }
+
+
+    @RabbitListener(queues = "emrais.oper.log.record.queue", ackMode = "MANUAL")
+    public void sendOperLogRecordMessage(OperationLogDTO operationLog, Message message, Channel channel) throws Exception {
+        operationLog.setOperationAddress(AddressUtils.getRealAddressByIP(operationLog.getOperationIp()));
+        operationLogMapper.addOperLog(operationLog);
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+    }
+
+    @RabbitListener(queues = "emrais.oper.error.record.queue", ackMode = "MANUAL")
+    public void sendOperErrorRecordMessage(AbnormalLogDTO abnormalLogDTO, Message message, Channel channel) throws Exception {
+        abnormalLogMapper.addOperErrorLog(abnormalLogDTO);
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+    }
+
 }

+ 41 - 0
security-center/src/main/java/com/lantone/security/component/MessageSender.java

@@ -1,5 +1,8 @@
 package com.lantone.security.component;
 
+import com.lantone.common.dto.AbnormalLogDTO;
+import com.lantone.common.dto.LoginLogDTO;
+import com.lantone.common.dto.OperationLogDTO;
 import com.lantone.security.enums.QueueEnum;
 import org.springframework.amqp.AmqpException;
 import org.springframework.amqp.core.Message;
@@ -33,4 +36,42 @@ public class MessageSender {
         });
     }
 
+    /**
+     * 用户登录成功后记录日志
+     */
+    public void sendLogSuccessRecordMessage(LoginLogDTO loginLog) {
+        rabbitTemplate.convertAndSend(QueueEnum.QUEUE_LOGIN_SUCESS_RECORD.getExchange(), QueueEnum.QUEUE_LOGIN_SUCESS_RECORD.getRouteKey(), loginLog, new MessagePostProcessor() {
+            @Override
+            public Message postProcessMessage(Message message) throws AmqpException {
+                message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
+                return message;
+            }
+        });
+    }
+
+    /**
+     * 用户操作后记录日志
+     */
+    public void sendOperLogRecordMessage(OperationLogDTO operationLog) {
+        rabbitTemplate.convertAndSend(QueueEnum.QUEUE_OPER_LOG_RECORD.getExchange(), QueueEnum.QUEUE_OPER_LOG_RECORD.getRouteKey(), operationLog, new MessagePostProcessor() {
+            @Override
+            public Message postProcessMessage(Message message) throws AmqpException {
+                message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
+                return message;
+            }
+        });
+    }
+
+    /**
+     * 用户操作异常记录日志
+     */
+    public void operErrorLogRecordMessage( AbnormalLogDTO abnormalLogDTO) {
+        rabbitTemplate.convertAndSend(QueueEnum.QUEUE_OPER_ERROR_RECORD.getExchange(), QueueEnum.QUEUE_OPER_ERROR_RECORD.getRouteKey(), abnormalLogDTO, new MessagePostProcessor() {
+            @Override
+            public Message postProcessMessage(Message message) throws AmqpException {
+                message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
+                return message;
+            }
+        });
+    }
 }

+ 81 - 0
security-center/src/main/java/com/lantone/security/config/RabbitMqConfig.java

@@ -45,4 +45,85 @@ public class RabbitMqConfig {
                 .with(QueueEnum.QUEUE_REDIS_CACHE_REFRESH.getRouteKey());
     }
 
+    /**
+     * 用户登录成功后记录日志需要刷新—队列所绑定的交换机
+     */
+    @Bean
+    DirectExchange loginSuccessRecordDirect() {
+        return ExchangeBuilder.directExchange(QueueEnum.QUEUE_LOGIN_SUCESS_RECORD.getExchange()).durable(true).build();
+    }
+
+    /**
+     * 用户登录成功后记录日志需要刷新—队列
+     */
+    @Bean
+    public Queue loginSuccessRecordQueue() {
+        return new Queue(QueueEnum.QUEUE_LOGIN_SUCESS_RECORD.getName(), true, false, false);
+    }
+
+
+    /**
+     * 用户登录成功后记录日志需要刷新-队列绑定到交换机
+     */
+    @Bean
+    Binding loginSuccessRecordBinding(DirectExchange loginSuccessRecordDirect, Queue loginSuccessRecordQueue) {
+        return BindingBuilder
+                .bind(loginSuccessRecordQueue)
+                .to(loginSuccessRecordDirect)
+                .with(QueueEnum.QUEUE_LOGIN_SUCESS_RECORD.getRouteKey());
+    }
+
+    /**
+     * 用户操作后记录日志需要刷新—队列所绑定的交换机
+     */
+    @Bean
+    DirectExchange operLogRecordDirect() {
+        return ExchangeBuilder.directExchange(QueueEnum.QUEUE_OPER_LOG_RECORD.getExchange()).durable(true).build();
+    }
+
+    /**
+     * 用户操作后记录日志需要刷新—队列
+     */
+    @Bean
+    public Queue operLogRecordQueue() {
+        return new Queue(QueueEnum.QUEUE_OPER_LOG_RECORD.getName(), true, false, false);
+    }
+
+    /**
+     * 用户操作后记录日志需要刷新-队列绑定到交换机
+     */
+    @Bean
+    Binding operLogRecordBinding(DirectExchange operLogRecordDirect, Queue operLogRecordQueue) {
+        return BindingBuilder
+                .bind(operLogRecordQueue)
+                .to(operLogRecordDirect)
+                .with(QueueEnum.QUEUE_OPER_LOG_RECORD.getRouteKey());
+    }
+
+    /**
+     * 用户操作异常记录日志需要刷新—队列所绑定的交换机
+     */
+    @Bean
+    DirectExchange operErrorRecordDirect() {
+        return ExchangeBuilder.directExchange(QueueEnum.QUEUE_OPER_ERROR_RECORD.getExchange()).durable(true).build();
+    }
+
+    /**
+     * 用户操作异常记录日志需要刷新—队列
+     */
+    @Bean
+    public Queue operErrorRecordQueue() {
+        return new Queue(QueueEnum.QUEUE_OPER_ERROR_RECORD.getName(), true, false, false);
+    }
+
+    /**
+     * 用户操作异常记录日志需要刷新-队列绑定到交换机
+     */
+    @Bean
+    Binding operErrorRecordBinding(DirectExchange operErrorRecordDirect, Queue operErrorRecordQueue) {
+        return BindingBuilder
+                .bind(operErrorRecordQueue)
+                .to(operErrorRecordDirect)
+                .with(QueueEnum.QUEUE_OPER_ERROR_RECORD.getRouteKey());
+    }
 }

+ 16 - 1
security-center/src/main/java/com/lantone/security/enums/QueueEnum.java

@@ -13,7 +13,22 @@ public enum QueueEnum {
     /**
      * 消息通知队列-基础信息变更导致redis需要刷新
      */
-    QUEUE_REDIS_CACHE_REFRESH("emrais.redis.cache.refresh.direct", "emrais.redis.cache.refresh.queue", "emrais.redis.cache.refresh.routekey");
+    QUEUE_REDIS_CACHE_REFRESH("emrais.redis.cache.refresh.direct", "emrais.redis.cache.refresh.queue", "emrais.redis.cache.refresh.routekey"),
+
+    /**
+     * 消息通知队列-用户登录成功后记录日志
+     */
+    QUEUE_LOGIN_SUCESS_RECORD("emrais.login.success.record.direct", "emrais.login.success.record.queue", "emrais.login.success.record.routekey"),
+
+    /**
+     * 消息通知队列-用户操作后记录日志
+     */
+    QUEUE_OPER_LOG_RECORD("emrais.oper.log.record.direct", "emrais.oper.log.record.queue", "emrais.oper.log.record.routekey"),
+
+    /**
+     * 消息通知队列-用户操作异常记录日志
+     */
+    QUEUE_OPER_ERROR_RECORD("emrais.oper.error.record.direct", "emrais.oper.error.record.queue", "emrais.oper.error.record.routekey");
 
     /**
      * 交换名称

+ 59 - 12
security-center/src/main/java/com/lantone/security/facade/UserManagementFacade.java

@@ -1,6 +1,8 @@
 package com.lantone.security.facade;
 
 import cn.hutool.crypto.digest.BCrypt;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -14,6 +16,7 @@ import com.lantone.common.dto.GetUserDTO;
 import com.lantone.common.dto.GetUserHospitalDeptDTO;
 import com.lantone.common.dto.GetUserHospitalsDTO;
 import com.lantone.common.dto.GetUserPageDTO;
+import com.lantone.common.dto.LoginLogDTO;
 import com.lantone.common.dto.SoftwareDTO;
 import com.lantone.common.dto.UserInfoDTO;
 import com.lantone.common.dto.UserRoleDTO;
@@ -23,6 +26,7 @@ import com.lantone.common.enums.StatusEnum;
 import com.lantone.common.exception.Asserts;
 import com.lantone.common.util.DateUtil;
 import com.lantone.common.util.EntityUtil;
+import com.lantone.common.util.HttpUtils;
 import com.lantone.common.util.ListUtil;
 import com.lantone.common.util.StringUtil;
 import com.lantone.common.util.SysUserUtils;
@@ -50,6 +54,7 @@ import com.lantone.dblayermbg.facade.MedoupDoctorFacade;
 import com.lantone.dblayermbg.facade.RoleFacade;
 import com.lantone.dblayermbg.facade.UserFacade;
 import com.lantone.dblayermbg.facade.UserRoleFacade;
+import com.lantone.security.component.MessageSender;
 import com.lantone.security.enums.DataAuthDataTypeEnum;
 import com.lantone.security.enums.DataAuthDetailTypeEnum;
 import com.lantone.security.enums.DictionaryEnum;
@@ -57,6 +62,8 @@ import com.lantone.security.enums.HospitalTypeEnum;
 import com.lantone.security.enums.RelationEnum;
 import com.lantone.security.enums.ReturnTypeEnum;
 import com.lantone.security.service.AuthService;
+import eu.bitwalker.useragentutils.UserAgent;
+import org.apache.commons.collections4.MapUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.crypto.factory.PasswordEncoderFactories;
@@ -64,7 +71,9 @@ import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Component;
 import org.springframework.util.DigestUtils;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -105,6 +114,8 @@ public class UserManagementFacade {
     private DoctorFacade doctorfacade;
     @Autowired
     private DictionaryInfoFacade dictionaryInfoFacade;
+    @Autowired
+    private MessageSender messageSender;
 
     public CommonResult login(LoginVO loginVO) {
         Map<String, String> params = new HashMap<>();
@@ -114,6 +125,7 @@ public class UserManagementFacade {
         params.put("username", loginVO.getUsername());
         params.put("password", loginVO.getPassword());
         CommonResult restResult = authService.getAccessToken(params);
+        sendLogRecordMessage(restResult);
         return restResult;
     }
 
@@ -288,6 +300,7 @@ public class UserManagementFacade {
             }
         }
     }
+
     /**
      * 修改密码
      *
@@ -301,11 +314,11 @@ public class UserManagementFacade {
         String MD5ModifyPassword = BCrypt.hashpw(modifyPassword);
         //对传入的密码进行格式验证
         Long hospitalID = SysUserUtils.getCurrentHospitalId();
-        Boolean regularBoolean = passwordRegular(modifyPassword,hospitalID+"");
-        if(!regularBoolean){
+        Boolean regularBoolean = passwordRegular(modifyPassword, hospitalID + "");
+        if (!regularBoolean) {
             Asserts.fail("请输入正确格式的新密码");
         }
-        String userId = SysUserUtils.getCurrentPrincipleId()+"";
+        String userId = SysUserUtils.getCurrentPrincipleId() + "";
         User user = userFacade.getOne(new QueryWrapper<User>()
                 .eq("is_deleted", IsDeleteEnum.N.getKey())
                 .eq("status", StatusEnum.Enable.getKey())
@@ -329,24 +342,26 @@ public class UserManagementFacade {
 
     /**
      * 未加密密文正则表达式  至少8个字符,1个大写字母,1个小写字母,1个数字和1个特殊字符:
+     *
      * @param password
      * @return
      */
-    public Boolean passwordRegular(String password,String hospitalId){
-        boolean check=true;
+    public Boolean passwordRegular(String password, String hospitalId) {
+        boolean check = true;
         Map<String, Map<String, String>> dictionaryWithKey = dictionaryInfoFacade.getDicMap(ReturnTypeEnum.INTERFACE.getKey(),
-                Lists.newArrayList(DictionaryEnum.PASSWORD.getKey()+""));
-        if(dictionaryWithKey!=null){
-            Map<String, String> stringStringMap = dictionaryWithKey.get(DictionaryEnum.PASSWORD.getKey()+"");
-            if(stringStringMap!=null) {
+                Lists.newArrayList(DictionaryEnum.PASSWORD.getKey() + ""));
+        if (dictionaryWithKey != null) {
+            Map<String, String> stringStringMap = dictionaryWithKey.get(DictionaryEnum.PASSWORD.getKey() + "");
+            if (stringStringMap != null) {
                 String regular = stringStringMap.get("check");
-                if(StringUtil.isNotEmpty(regular)) {
+                if (StringUtil.isNotEmpty(regular)) {
                     check = password.matches(regular);
                 }
             }
         }
         return check;
     }
+
     /**
      * @param roles
      * @Description插入角色校验
@@ -354,7 +369,7 @@ public class UserManagementFacade {
      */
     private void checkRoles(List<Long> roles) {
         if (ListUtil.isNotEmpty(roles)) {
-            if (roles.size() != roleFacade.getBaseMapper().getCount(roles,StatusEnum.Enable.getKey(), IsDeleteEnum.N.getKey())) {
+            if (roles.size() != roleFacade.getBaseMapper().getCount(roles, StatusEnum.Enable.getKey(), IsDeleteEnum.N.getKey())) {
                 Asserts.fail("插入用户角色列表有改动,请刷新页面重新操作");
             }
         }
@@ -749,7 +764,9 @@ public class UserManagementFacade {
      * @Return java.util.List<com.lantone.common.dto.GetUserHospitalsDTO>
      */
     private List<GetUserHospitalsDTO> transTreeData(Map<Long, List<GetUserHospitalsDTO>> softwareHospitalMap, List<GetUserHospitalsDTO> softwareHospitals) {
-        if (softwareHospitalMap == null) return null;
+        if (softwareHospitalMap == null) {
+            return null;
+        }
         List<GetUserHospitalsDTO> out = new ArrayList<>();
         Set<Long> tempParents = new HashSet<>();
         Set<Long> parents = softwareHospitalMap.keySet();
@@ -771,4 +788,34 @@ public class UserManagementFacade {
         });
         return out;
     }
+
+    /**
+     * @Description: 用户获取token后发送登录信息
+     * @Param: [commonResult]
+     * @return: void
+     * @Author: cy
+     * @Date: 2021/9/5
+     */
+    public void sendLogRecordMessage(CommonResult commonResult) {
+        Object data = commonResult.getData();
+        Map<String, Object> map = JSONObject.parseObject(JSON.toJSONString(data));
+        if (map.containsKey("token") && null != map.get("token")) {
+            LoginLogDTO loginLog = new LoginLogDTO();
+            Date date = new Date();
+            loginLog.setLoginDate(date);
+            loginLog.setGmtCreate(date);
+            String token = map.get("token").toString();
+            UserDto userByToken = SysUserUtils.getUserByToken(token);
+            loginLog.setLoginId(userByToken.getId());
+            loginLog.setLoginName(userByToken.getUserName());
+            loginLog.setLoginIp(HttpUtils.getIpAddress());
+            UserAgent userAgent = UserAgent.parseUserAgentString(HttpUtils.getHttpServletRequest().getHeader("User-Agent"));
+            // 获取客户端浏览器
+            String browser = userAgent.getBrowser().getName();
+            loginLog.setLoginBrowser(browser);
+            messageSender.sendLogSuccessRecordMessage(loginLog);
+        }
+    }
+
+    ;
 }