|
|
@@ -18,6 +18,8 @@ import com.fs.common.core.redis.RedisCache;
|
|
|
import com.fs.common.enums.BusinessType;
|
|
|
import com.fs.common.exception.ServiceException;
|
|
|
import com.fs.common.service.ISmsService;
|
|
|
+import com.fs.common.utils.ServletUtils;
|
|
|
+import com.fs.common.utils.ip.IpUtils;
|
|
|
import com.fs.common.utils.sign.Md5Utils;
|
|
|
import com.fs.core.config.WxOpenProperties;
|
|
|
import com.fs.course.domain.LuckyBag;
|
|
|
@@ -61,6 +63,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
@@ -417,6 +420,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
}
|
|
|
// 检测im是否创建用户
|
|
|
openIMService. accountCheck("U"+user.getUserId(),"1");
|
|
|
+ recordLoginInfo(user.getUserId(), param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
int isFirstLogin = userNewTaskService.performTaskOne(user.getUserId());
|
|
|
String token = jwtUtils.generateToken(user.getUserId());
|
|
|
redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
|
|
|
@@ -491,6 +495,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
if (user.getStatus()==0){
|
|
|
return R.error("登录失败,账户被禁用");
|
|
|
}
|
|
|
+ recordLoginInfo(user.getUserId(), param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
int isFirstLogin = userNewTaskService.performTaskOne(user.getUserId());
|
|
|
String token = jwtUtils.generateToken(user.getUserId());
|
|
|
redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
|
|
|
@@ -580,9 +585,12 @@ public class AppLoginController extends AppBaseController{
|
|
|
}
|
|
|
|
|
|
FsUser info=user.get(0);
|
|
|
+ String lastIp = map.get("lastIp");
|
|
|
+ String loginDevice = map.get("loginDevice");
|
|
|
+ String source = map.get("source");
|
|
|
|
|
|
if (ObjectUtil.isNotEmpty(isWechatInstalled)&&isWechatInstalled && isInit()){
|
|
|
- return generateTokenAndReturn(info);
|
|
|
+ return generateTokenAndReturn(info, lastIp, loginDevice, source);
|
|
|
}
|
|
|
// 与 /login 一致:无 unionId 时返回 isNew,前端强制绑定微信
|
|
|
if (info.getUnionId()==null){
|
|
|
@@ -601,7 +609,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
userService.updateFsUser(fsUser);
|
|
|
logger.info("zyp \n【手机加密】:{}",encryptPhone(phone));
|
|
|
}
|
|
|
- return R.ok(generateTokenAndReturn(info)).put("isNew",true).put("phone",encryptPhone(phone));
|
|
|
+ return R.ok(generateTokenAndReturn(info, lastIp, loginDevice, source)).put("isNew",true).put("phone",encryptPhone(phone));
|
|
|
}
|
|
|
FsUser userMap = new FsUser();
|
|
|
userMap.setUserId(info.getUserId());
|
|
|
@@ -615,7 +623,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
userMap.setUpdateTime(new Date());
|
|
|
userService.updateFsUser(userMap);
|
|
|
|
|
|
- return generateTokenAndReturn(info);
|
|
|
+ return generateTokenAndReturn(info, lastIp, loginDevice, source);
|
|
|
}
|
|
|
|
|
|
@PostMapping("/resetPassword")
|
|
|
@@ -793,6 +801,15 @@ public class AppLoginController extends AppBaseController{
|
|
|
}
|
|
|
|
|
|
private R generateTokenAndReturn(FsUser user) {
|
|
|
+ return generateTokenAndReturn(user, null, null, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private R generateTokenAndReturn(FsUser user, String lastIp) {
|
|
|
+ return generateTokenAndReturn(user, lastIp, null, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private R generateTokenAndReturn(FsUser user, String lastIp, String loginDevice, String source) {
|
|
|
+ recordLoginInfo(user.getUserId(), lastIp, loginDevice, source);
|
|
|
String token = jwtUtils.generateToken(user.getUserId());
|
|
|
redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
|
|
|
int isFirstLogin = userNewTaskService.performTaskOne(user.getUserId());
|
|
|
@@ -803,6 +820,124 @@ public class AppLoginController extends AppBaseController{
|
|
|
return R.ok(map);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 解析登录IP:优先外网IP。
|
|
|
+ * 1. 前端传入且为外网IP时直接使用
|
|
|
+ * 2. 否则从请求头(X-Forwarded-For / X-Real-IP 等)中取第一个外网IP
|
|
|
+ * 3. 都拿不到外网IP时再回退到可用IP
|
|
|
+ */
|
|
|
+ private String resolveLoginIp(String lastIp) {
|
|
|
+ if (StringUtils.isNotEmpty(lastIp)) {
|
|
|
+ String clientIp = extractFirstIp(lastIp);
|
|
|
+ if (StringUtils.isNotEmpty(clientIp) && !isInternalIp(clientIp)) {
|
|
|
+ return clientIp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return getExternalIpFromRequest();
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.warn("获取登录IP失败:{}", e.getMessage());
|
|
|
+ return StringUtils.isNotEmpty(lastIp) ? extractFirstIp(lastIp) : null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从请求中尽量获取外网IP
|
|
|
+ */
|
|
|
+ private String getExternalIpFromRequest() {
|
|
|
+ HttpServletRequest request = ServletUtils.getRequest();
|
|
|
+ if (request == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String[] headerNames = {
|
|
|
+ "X-Forwarded-For",
|
|
|
+ "x-forwarded-for",
|
|
|
+ "X-Real-IP",
|
|
|
+ "Proxy-Client-IP",
|
|
|
+ "WL-Proxy-Client-IP",
|
|
|
+ "HTTP_CLIENT_IP",
|
|
|
+ "HTTP_X_FORWARDED_FOR"
|
|
|
+ };
|
|
|
+ String fallbackIp = null;
|
|
|
+ for (String header : headerNames) {
|
|
|
+ String value = request.getHeader(header);
|
|
|
+ if (StringUtils.isEmpty(value) || "unknown".equalsIgnoreCase(value)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // X-Forwarded-For 可能为 "外网IP, 代理IP1, 代理IP2"
|
|
|
+ for (String part : value.split(",")) {
|
|
|
+ String ip = extractFirstIp(part);
|
|
|
+ if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!isInternalIp(ip)) {
|
|
|
+ return ip;
|
|
|
+ }
|
|
|
+ if (fallbackIp == null) {
|
|
|
+ fallbackIp = ip;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String remoteAddr = request.getRemoteAddr();
|
|
|
+ if ("0:0:0:0:0:0:0:1".equals(remoteAddr)) {
|
|
|
+ remoteAddr = "127.0.0.1";
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(remoteAddr) && !isInternalIp(remoteAddr)) {
|
|
|
+ return remoteAddr;
|
|
|
+ }
|
|
|
+ return fallbackIp != null ? fallbackIp : remoteAddr;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String extractFirstIp(String ip) {
|
|
|
+ if (StringUtils.isEmpty(ip)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String value = ip.trim();
|
|
|
+ if (value.contains(",")) {
|
|
|
+ value = value.split(",")[0].trim();
|
|
|
+ }
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isInternalIp(String ip) {
|
|
|
+ if (StringUtils.isEmpty(ip)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return IpUtils.internalIp(ip)
|
|
|
+ || "127.0.0.1".equals(ip)
|
|
|
+ || "localhost".equalsIgnoreCase(ip)
|
|
|
+ || "0:0:0:0:0:0:0:1".equals(ip)
|
|
|
+ || "::1".equals(ip);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录登录信息:lastIp / loginDevice / source(有值才更新)
|
|
|
+ */
|
|
|
+ private void recordLoginInfo(Long userId, String lastIp, String loginDevice, String source) {
|
|
|
+ if (userId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ FsUser update = new FsUser();
|
|
|
+ update.setUserId(userId);
|
|
|
+ boolean needUpdate = false;
|
|
|
+ String ip = resolveLoginIp(lastIp);
|
|
|
+ if (StringUtils.isNotEmpty(ip)) {
|
|
|
+ update.setLastIp(ip);
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(loginDevice)) {
|
|
|
+ update.setLoginDevice(loginDevice);
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(source)) {
|
|
|
+ update.setSource(source);
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+ if (needUpdate) {
|
|
|
+ userService.updateFsUser(update);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// private R handleLoginType1(FsUserLoginParam param) {
|
|
|
// if (StringUtils.isEmpty(param.getPhone()) || StringUtils.isEmpty(param.getPassword())) {
|
|
|
// return R.error("账号或密码不能为空");
|
|
|
@@ -845,7 +980,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
if (usersByPhone.size()==1){
|
|
|
user = usersByPhone.get(0);
|
|
|
if (ObjectUtil.isNotEmpty(isWechatInstalled)&&isWechatInstalled && isInit()){
|
|
|
- return generateTokenAndReturn(user);
|
|
|
+ return generateTokenAndReturn(user, param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
}
|
|
|
if (user.getUnionId()==null){
|
|
|
if (user.getPhone().length()<=11){
|
|
|
@@ -855,7 +990,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
userMapper.updateFsUser(fsUser);
|
|
|
logger.info("zyp \n【手机加密】:{}",encryptPhone(param.getPhone()));
|
|
|
}
|
|
|
- return R.ok(generateTokenAndReturn(user)).put("isNew",true).put("phone",encryptPhone(param.getPhone()));
|
|
|
+ return R.ok(generateTokenAndReturn(user, param.getLastIp(), param.getLoginDevice(), param.getSource())).put("isNew",true).put("phone",encryptPhone(param.getPhone()));
|
|
|
}
|
|
|
// 校验用户是否存在及账号状态
|
|
|
if (user == null) {
|
|
|
@@ -883,7 +1018,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
//fsUserTalentService.addFsUserTalent(fsUser.getUserId());
|
|
|
openIMService. accountCheck("U"+user.getUserId(),"1");
|
|
|
|
|
|
- return generateTokenAndReturn(user);
|
|
|
+ return generateTokenAndReturn(user, param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
}else {
|
|
|
return R.ok().put("users",usersByPhone);
|
|
|
}
|
|
|
@@ -1004,7 +1139,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
if (usersByPhone.size()==1){
|
|
|
user = usersByPhone.get(0);
|
|
|
if (ObjectUtil.isNotEmpty(isWechatInstalled)&&isWechatInstalled && isInit()){
|
|
|
- return generateTokenAndReturn(user);
|
|
|
+ return generateTokenAndReturn(user, param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
}
|
|
|
if (user.getUnionId()==null){
|
|
|
if (user.getPhone().length()<=11){
|
|
|
@@ -1014,6 +1149,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
userMapper.updateFsUser(fsUser);
|
|
|
logger.info("zyp \n【手机加密】:{}",encryptPhone(param.getPhone()));
|
|
|
}
|
|
|
+ recordLoginInfo(user.getUserId(), param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
return R.ok().put("isNew",true).put("phone",encryptPhone(param.getPhone()));
|
|
|
}
|
|
|
if (StringUtils.isNotEmpty(param.getJpushId())) {
|
|
|
@@ -1029,7 +1165,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
return R.ok().put("users",usersByPhone);
|
|
|
}
|
|
|
openIMService. accountCheck("U"+user.getUserId(),"1");
|
|
|
- return generateTokenAndReturn(user);
|
|
|
+ return generateTokenAndReturn(user, param.getLastIp(), param.getLoginDevice(), param.getSource());
|
|
|
}
|
|
|
|
|
|
/* @PostMapping("/loginByUserId")
|
|
|
@@ -1057,6 +1193,7 @@ public class AppLoginController extends AppBaseController{
|
|
|
if (StringUtils.isNotEmpty(param.getJpushId())) {
|
|
|
newUser.setJpushId(param.getJpushId());
|
|
|
}
|
|
|
+ newUser.setLastIp(resolveLoginIp(param.getLastIp()));
|
|
|
userService.insertFsUser(newUser);
|
|
|
return newUser;
|
|
|
}
|