瀏覽代碼

登录/登出

lrf 8 月之前
父節點
當前提交
422f02e7a6

+ 1 - 1
src/main/java/com/free/InterceptorConfig.java

@@ -11,7 +11,7 @@ import com.free.frame.AuthenticationInterceptor;
 public class InterceptorConfig implements WebMvcConfigurer {
 public class InterceptorConfig implements WebMvcConfigurer {
   @Override
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
   public void addInterceptors(InterceptorRegistry registry) {
-    registry.addInterceptor(authenticationInterceptor()).excludePathPatterns("/login/**")
+    registry.addInterceptor(authenticationInterceptor()).excludePathPatterns("/kf/login/**", "/kf/logout")
         .addPathPatterns("/**");
         .addPathPatterns("/**");
   }
   }
 
 

+ 12 - 3
src/main/java/com/free/controller/LoginController.java

@@ -5,7 +5,6 @@ import java.util.Map;
 import javax.validation.Valid;
 import javax.validation.Valid;
 
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -26,7 +25,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 
 
 @RestController
 @RestController
-@RequestMapping("/login")
+@RequestMapping
 @Api(tags = "登录服务")
 @Api(tags = "登录服务")
 public class LoginController {
 public class LoginController {
 
 
@@ -39,7 +38,7 @@ public class LoginController {
   private AdminService adminService;
   private AdminService adminService;
 
 
   @ApiOperation("客服服务登录")
   @ApiOperation("客服服务登录")
-  @PostMapping("/{type}")
+  @PostMapping("/kf/login/{type}")
   public Object login(@PathVariable String type, @RequestBody @Valid LoginDTO data) {
   public Object login(@PathVariable String type, @RequestBody @Valid LoginDTO data) {
     Map<String, Object> userInfo = null;
     Map<String, Object> userInfo = null;
     if (this.adminLoginType.equals(type)) {
     if (this.adminLoginType.equals(type)) {
@@ -70,4 +69,14 @@ public class LoginController {
     return ResponseFormat.success(code);
     return ResponseFormat.success(code);
 
 
   }
   }
+
+  @ApiOperation("客服服务登出")
+  @PostMapping("/kf/logout")
+  public Object logout() {
+    // 获取token,然后注销
+    String token = JwtUtil.getToken();
+    JwtUtil.logOff(token);
+    return ResponseFormat.success();
+  }
+
 }
 }

+ 11 - 5
src/main/java/com/free/entity/system/LoginRecord.java

@@ -4,6 +4,7 @@ import java.time.LocalDateTime;
 
 
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.format.annotation.DateTimeFormat;
 
 
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -42,7 +43,7 @@ public class LoginRecord {
   private String type; // Admin, User
   private String type; // Admin, User
 
 
   @Column(comment = "token", type = MySqlTypeConstant.TEXT)
   @Column(comment = "token", type = MySqlTypeConstant.TEXT)
-  @TableField(value = "token")
+  @TableField(value = "token", updateStrategy = FieldStrategy.ALWAYS)
   @ApiModelProperty("token")
   @ApiModelProperty("token")
   private String token;
   private String token;
 
 
@@ -53,10 +54,15 @@ public class LoginRecord {
   @ApiModelProperty("过期时间")
   @ApiModelProperty("过期时间")
   private LocalDateTime expire_time;
   private LocalDateTime expire_time;
 
 
-  @Column(comment = "最后登录时间")
-  @TableField(value = "last_login_time")
+  @Column(comment = "最后使用时间")
+  @TableField(value = "last_time")
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
   @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
   @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-  @ApiModelProperty("最后登录时间")
-  private LocalDateTime last_login_time;
+  @ApiModelProperty("最后使用时间")
+  private LocalDateTime last_time;
+
+  @Column(comment = "最后使用ip")
+  @TableField(value = "last_ip")
+  @ApiModelProperty("最后使用ip")
+  private String last_ip;
 }
 }

+ 1 - 9
src/main/java/com/free/frame/AuthenticationInterceptor.java

@@ -28,15 +28,7 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
         return true;
         return true;
       }
       }
     }
     }
-    // 执行认证
-    String tokenHeader = request.getHeader(JwtUtil.TOKEN_HEADER);// 从 http 请求头中取出 token
-    if (tokenHeader == null) {
-      throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
-    }
-    String token = tokenHeader.replace(JwtUtil.TOKEN_PREFIX, "");
-    if (token == null) {
-      throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
-    }
+    String token = JwtUtil.getToken();
     // 1.查询数据库中该用户的时间是否超时: 如果有问题,验证函数内会抛异常
     // 1.查询数据库中该用户的时间是否超时: 如果有问题,验证函数内会抛异常
     JwtUtil.verify(token);
     JwtUtil.verify(token);
     // 2.没超时则,自动续时
     // 2.没超时则,自动续时

+ 2 - 1
src/main/java/com/free/frame/ExceptionEnum.java

@@ -11,8 +11,9 @@ public enum ExceptionEnum {
   PASSWORD_ERROR("4012", "密码错误"),
   PASSWORD_ERROR("4012", "密码错误"),
   TOKEN_NOT_FOUND("4013", "未找到登录信息"),
   TOKEN_NOT_FOUND("4013", "未找到登录信息"),
   TOKEN_INVALID("4014", "登录已超时,请重新登录"),
   TOKEN_INVALID("4014", "登录已超时,请重新登录"),
-  TOKEN_ERROR("4015", "登录信息可能被篡改,请重新登录"),
+  TOKEN_ERROR("4015", "该账号已在其他地点登录,请重新登录"),
   NO_LOGIN_RECORD("4016", "未找到登录信息,请重新登录"),
   NO_LOGIN_RECORD("4016", "未找到登录信息,请重新登录"),
+  ACCOUNT_IS_LOGOUT("4017","该用户已登出,如要使用请重新登录"),
   // 数据操作异常定义
   // 数据操作异常定义
   NOT_FOUND("404", "数据不存在或已删除!");
   NOT_FOUND("404", "数据不存在或已删除!");
 
 

+ 83 - 13
src/main/java/com/free/utils/JwtUtil.java

@@ -19,9 +19,14 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
 
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
 @Component
 @Component
 public class JwtUtil {
 public class JwtUtil {
   public static final String TOKEN_HEADER = "Authorization";
   public static final String TOKEN_HEADER = "Authorization";
@@ -78,6 +83,36 @@ public class JwtUtil {
     return returnToken;
     return returnToken;
   }
   }
 
 
+  /**
+   * 注销用户,退出登录
+   * 将token置空,在校验的时候会处理没有token的情况
+   * 
+   * @param token
+   */
+  public static void logOff(String token) {
+    Map<String, Object> map = getDetails(token);
+    Long user_id = (Long) map.get("id");
+    String type = (String) map.get("type");
+    QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
+    qw.eq("user_id", user_id);
+    qw.eq("type", type);
+    LoginRecord record = jwtUtil.lrs.getOne(qw);
+    // 没找到数据不需要处理
+    if (null == record) {
+      return;
+    }
+    // token不一致,不需要处理
+    String dbToken = record.getToken();
+    if (null==dbToken || !dbToken.equals(token)) {
+      return;
+    }
+    // token置空
+    LoginRecord lr = new LoginRecord();
+    lr.setToken(null);
+    lr.setId(record.getId());
+    jwtUtil.lrs.updateById(lr);
+  }
+
   /**
   /**
    * 创建登录数据
    * 创建登录数据
    * 
    * 
@@ -89,30 +124,31 @@ public class JwtUtil {
     String type = (String) map.get("type");
     String type = (String) map.get("type");
     // 第一次登录是创建,以后都是更新, 每个用户都有1个登录数据,但是能否使用要看过期时间
     // 第一次登录是创建,以后都是更新, 每个用户都有1个登录数据,但是能否使用要看过期时间
     QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
     QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
-    // qw.eq("user_id", user_id);
-    // qw.eq("type", type);
-    Map<String,Object> qm = new HashMap<>();
-    qm.put("user_id",user_id);
-    qm.put("type",type);
-    qw.allEq(qm);
+    qw.eq("user_id", user_id);
+    qw.eq("type", type);
     LoginRecord histroy = jwtUtil.lrs.getOne(qw);
     LoginRecord histroy = jwtUtil.lrs.getOne(qw);
-    LocalDateTime last_login_time = LocalDateTime.now();
+    // 准备数据
+    LocalDateTime last_time = LocalDateTime.now();
     LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
     LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
+    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    String ip = request.getRemoteAddr();
     if (null == histroy) {
     if (null == histroy) {
       // 创建数据
       // 创建数据
       LoginRecord lr = new LoginRecord();
       LoginRecord lr = new LoginRecord();
       lr.setExpire_time(expire_time);
       lr.setExpire_time(expire_time);
-      lr.setLast_login_time(last_login_time);
+      lr.setLast_time(last_time);
       lr.setToken(token);
       lr.setToken(token);
       lr.setType(type);
       lr.setType(type);
       lr.setUser_id(user_id);
       lr.setUser_id(user_id);
+      lr.setLast_ip(ip);
       jwtUtil.lrs.save(lr);
       jwtUtil.lrs.save(lr);
     } else {
     } else {
       // 修改数据
       // 修改数据
       LoginRecord lr = new LoginRecord();
       LoginRecord lr = new LoginRecord();
       lr.setExpire_time(expire_time);
       lr.setExpire_time(expire_time);
-      lr.setLast_login_time(last_login_time);
+      lr.setLast_time(last_time);
       lr.setToken(token);
       lr.setToken(token);
+      lr.setLast_ip(ip);
       lr.setId(histroy.getId());
       lr.setId(histroy.getId());
       jwtUtil.lrs.updateById(lr);
       jwtUtil.lrs.updateById(lr);
     }
     }
@@ -127,18 +163,24 @@ public class JwtUtil {
     Map<String, Object> map = getDetails(token);
     Map<String, Object> map = getDetails(token);
     Long user_id = (Long) map.get("id");
     Long user_id = (Long) map.get("id");
     String type = (String) map.get("type");
     String type = (String) map.get("type");
-    LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
     QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
     QueryWrapper<LoginRecord> qw = new QueryWrapper<>();
     qw.eq("user_id", user_id).eq("type", type);
     qw.eq("user_id", user_id).eq("type", type);
     LoginRecord histroy = jwtUtil.lrs.getOne(qw);
     LoginRecord histroy = jwtUtil.lrs.getOne(qw);
+    // 准备数据
+    LocalDateTime expire_time = LocalDateTime.now().plusMinutes(EXPIRE_MIN);
+    LocalDateTime last_time = LocalDateTime.now();
+    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    String ip = request.getRemoteAddr();
     if (null == histroy) {
     if (null == histroy) {
       // 没有数据,转至创建
       // 没有数据,转至创建
       createLoginRecord(token);
       createLoginRecord(token);
     } else {
     } else {
-      // 修改过期时间
+      // 修改过期时间,使用时间,使用ip
       LoginRecord lr = new LoginRecord();
       LoginRecord lr = new LoginRecord();
       lr.setExpire_time(expire_time);
       lr.setExpire_time(expire_time);
       lr.setId(histroy.getId());
       lr.setId(histroy.getId());
+      lr.setLast_ip(ip);
+      lr.setLast_time(last_time);
       jwtUtil.lrs.updateById(lr);
       jwtUtil.lrs.updateById(lr);
     }
     }
   }
   }
@@ -166,12 +208,22 @@ public class JwtUtil {
     if (null == histroy) {
     if (null == histroy) {
       throw new CustomizationException(ExceptionEnum.NO_LOGIN_RECORD);
       throw new CustomizationException(ExceptionEnum.NO_LOGIN_RECORD);
     }
     }
+    // 获取数据库的token
+    String dbToken = histroy.getToken();
+    if (null == dbToken) {
+      throw new CustomizationException(ExceptionEnum.ACCOUNT_IS_LOGOUT);
+    }
     // 取出过期时间,和当前时间进行比较
     // 取出过期时间,和当前时间进行比较
     LocalDateTime nowTime = LocalDateTime.now();
     LocalDateTime nowTime = LocalDateTime.now();
-    boolean is_before = histroy.getExpire_time().isBefore(nowTime);
-    if (!is_before) {
+    boolean is_after = histroy.getExpire_time().isAfter(nowTime);
+    if (!is_after) {
       throw new CustomizationException(ExceptionEnum.TOKEN_INVALID);
       throw new CustomizationException(ExceptionEnum.TOKEN_INVALID);
     }
     }
+    // token对比,如果时间允许,但是token码不一致,则说明在其他地点登录
+    if (!dbToken.equals(token)) {
+      throw new CustomizationException(ExceptionEnum.TOKEN_ERROR);
+    }
+    // 如果需要校准 ip,再加上即可
   }
   }
 
 
   /**
   /**
@@ -199,4 +251,22 @@ public class JwtUtil {
       return null;
       return null;
     }
     }
   }
   }
+
+  /**
+   * 根据请求头获取token
+   * 
+   * @return
+   */
+  public static String getToken() {
+    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    String tokenHeader = request.getHeader(TOKEN_HEADER);
+    if (tokenHeader == null) {
+      throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
+    }
+    String token = tokenHeader.replace(JwtUtil.TOKEN_PREFIX, "");
+    if (token == null) {
+      throw new CustomizationException(ExceptionEnum.TOKEN_NOT_FOUND);
+    }
+    return token;
+  }
 }
 }