添加了显示IP归属地的功能

pull/2/head
zhong-hongye12355 2 months ago
parent 3adff4bbe0
commit d6b42b25d3

@ -32,8 +32,16 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.36</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration; import java.time.Duration;
@ -38,14 +39,14 @@ public class UserController {
@ApiOperation(value = "用户注册") @ApiOperation(value = "用户注册")
@PostMapping("register") @PostMapping("register")
public Result register(@RequestBody RegisterDTO registerDTO) { public Result register(@RequestBody RegisterDTO registerDTO, HttpServletRequest request) {
return userService.register(registerDTO); return userService.register(registerDTO,request);
} }
@ApiOperation(value = "用户登录") @ApiOperation(value = "用户登录")
@PostMapping("login") @PostMapping("login")
public Result login(@RequestBody LoginDTO loginDTO) { public Result login(@RequestBody LoginDTO loginDTO,HttpServletRequest request) {
Result login = userService.login(loginDTO); Result login = userService.login(loginDTO,request);
//登陆成功后生成jwt令牌 //登陆成功后生成jwt令牌
LoginVO vo=(LoginVO) login.getData(); LoginVO vo=(LoginVO) login.getData();
if (vo == null) { if (vo == null) {
@ -62,16 +63,16 @@ public class UserController {
@ApiOperation(value = "获取邮箱验证码") @ApiOperation(value = "获取邮箱验证码")
@PostMapping("code") @PostMapping("code")
public Result getCode(@RequestBody EmailDTO emailDto){ public Result getCode(@RequestBody EmailDTO emailDto,HttpServletRequest request) {
String email=emailDto.getEmail(); String email=emailDto.getEmail();
log.debug("收到的原始邮箱: {}", email); log.debug("收到的原始邮箱: {}", email);
return userService.sendVerificationCode(email); return userService.sendVerificationCode(email,request);
} }
@ApiOperation(value = "邮箱验证码登录") @ApiOperation(value = "邮箱验证码登录")
@PostMapping("login/code") @PostMapping("login/code")
public Result loginWithEmailCode(@RequestBody LoginEmailDTO loginEmailDTO){ public Result loginWithEmailCode(@RequestBody LoginEmailDTO loginEmailDTO,HttpServletRequest request) {
return userService.loginWithEmail(loginEmailDTO); return userService.loginWithEmail(loginEmailDTO,request);
} }
} }

@ -9,4 +9,6 @@ public interface UserMapper {
void insert(User user); void insert(User user);
User FindByEmail(@Param("email") String email, @Param("password") String password); User FindByEmail(@Param("email") String email, @Param("password") String password);
User getUserByEmail(String email); User getUserByEmail(String email);
void UpdateIPLocation(@Param("email") String email,@Param("loginIp") String loginIp);
User FindByOnlyEmail(@Param("email") String email);
} }

@ -16,6 +16,6 @@ public class LoginVO {
private Byte isVerified; private Byte isVerified;
private Byte status; private Byte status;
private String token; private String token;
private String LoginIp;
} }

@ -11,5 +11,5 @@ public class RegisterVO {
private Long id; private Long id;
private String username; private String username;
private String nickname; private String nickname;
private String loginIp;
} }

@ -0,0 +1,9 @@
package com.unilife.service;
import com.unilife.model.dto.LoginDTO;
import javax.servlet.http.HttpServletRequest;
public interface IPLocationService {
public String getIPLocation(String ip);
public String getClientIP(HttpServletRequest request);
}

@ -5,12 +5,15 @@ import com.unilife.model.dto.LoginDTO;
import com.unilife.model.dto.LoginEmailDTO; import com.unilife.model.dto.LoginEmailDTO;
import com.unilife.model.dto.RegisterDTO; import com.unilife.model.dto.RegisterDTO;
import javax.servlet.http.HttpServletRequest;
public interface UserService { public interface UserService {
Result register(RegisterDTO registerDTO); Result register(RegisterDTO registerDTO, HttpServletRequest request);
Result login(LoginDTO loginDTO);
Result login(LoginDTO loginDTO,HttpServletRequest request);
Result sendVerificationCode(String email); Result sendVerificationCode(String email,HttpServletRequest request);
Result loginWithEmail(LoginEmailDTO loginEmailDTO); Result loginWithEmail(LoginEmailDTO loginEmailDTO,HttpServletRequest request);
} }

@ -0,0 +1,77 @@
package com.unilife.service.impl;
import com.unilife.service.IPLocationService;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ResourceUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.FileNotFoundException;
@Service
public class IPLocationServicelmpl implements IPLocationService {
private Searcher searcher;
@Override
public String getIPLocation(String ip) {
if("127.0.0.1".equals(ip) || ip.startsWith("192.168")){
return "局域网 IP";
}
if(searcher == null){
try{
File file = ResourceUtils.getFile("classpath:ipdb/ip2region.xdb");
String dbPath = file.getPath();
//System.out.println(dbPath);
searcher = Searcher.newWithFileOnly(dbPath);
}
catch(FileNotFoundException e){
e.printStackTrace();
return "IP地址库文件未找到";
}
catch (IOException e){
e.printStackTrace();
return "IP地址库初始化失败";
}
}
String region = null;
String errormessage = null;
try{
region = searcher.search(ip);
}
catch (Exception e){
errormessage = e.getMessage();
if(errormessage != null && errormessage.length() > 256){
errormessage = errormessage.substring(0, 256);
}
e.printStackTrace();
return "IP归属地查找失败" + errormessage;
}
return (region == null) ? "未知归属地" : region;
}
@Override
public String getClientIP(HttpServletRequest request) {
if("127.0.0.1".equals(request.getRemoteAddr())){
return "14.21.80.0";
}//实际开发的时候删掉!
String ip = request.getHeader("X-forwarded-for");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return (ip != null) ? ip.split(",")[0] : null;
}
}

@ -11,6 +11,7 @@ import com.unilife.model.dto.RegisterDTO;
import com.unilife.model.entity.User; import com.unilife.model.entity.User;
import com.unilife.model.vo.LoginVO; import com.unilife.model.vo.LoginVO;
import com.unilife.model.vo.RegisterVO; import com.unilife.model.vo.RegisterVO;
import com.unilife.service.IPLocationService;
import com.unilife.service.UserService; import com.unilife.service.UserService;
import com.unilife.utils.JwtUtil; import com.unilife.utils.JwtUtil;
import com.unilife.utils.RegexUtils; import com.unilife.utils.RegexUtils;
@ -25,6 +26,7 @@ import org.springframework.stereotype.Service;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
@ -37,6 +39,9 @@ import static com.unilife.common.constant.RedisConstant.LOGIN_EMAIL_KEY;
@Service @Service
public class UserServiceImpl implements UserService { public class UserServiceImpl implements UserService {
@Autowired
private IPLocationService ipLocationService;
@Autowired @Autowired
private UserMapper userMapper; private UserMapper userMapper;
@ -56,19 +61,30 @@ public class UserServiceImpl implements UserService {
@Override @Override
public Result register(RegisterDTO registerDTO) { public Result register(RegisterDTO registerDTO, HttpServletRequest request) {
if(registerDTO.getEmail().isEmpty() || registerDTO.getPassword().isEmpty()) { if(registerDTO.getEmail().isEmpty() || registerDTO.getPassword().isEmpty()) {
return Result.error(400,"邮箱或密码不能为空"); return Result.error(400,"邮箱或密码不能为空");
} }
if(registerDTO.getPassword().length() < 6) {
return Result.error(400,"密码长度过短!");
}
User getuser = userMapper.FindByOnlyEmail(registerDTO.getEmail());
if(getuser != null) {
return Result.error(400,"用户已存在!");
}
User user = new User(); User user = new User();
BeanUtil.copyProperties(registerDTO,user); BeanUtil.copyProperties(registerDTO,user);
String IPAddress = ipLocationService.getClientIP(request);
String Location = ipLocationService.getIPLocation(IPAddress);
user.setLoginIp(Location);
userMapper.insert(user); userMapper.insert(user);
RegisterVO registerVO = new RegisterVO(user.getId(),user.getUsername(),user.getNickname()); RegisterVO registerVO = new RegisterVO(user.getId(),user.getUsername()
,user.getNickname(),user.getLoginIp());
return Result.success(registerVO); return Result.success(registerVO);
} }
@Override @Override
public Result login(LoginDTO loginDTO) { public Result login(LoginDTO loginDTO,HttpServletRequest request) {
User user = new User(); User user = new User();
BeanUtil.copyProperties(loginDTO,user);//将登录的前端传来的消息拷贝给这个user BeanUtil.copyProperties(loginDTO,user);//将登录的前端传来的消息拷贝给这个user
User getuser = userMapper.FindByEmail(user.getEmail(),user.getPassword()); User getuser = userMapper.FindByEmail(user.getEmail(),user.getPassword());
@ -80,13 +96,17 @@ public class UserServiceImpl implements UserService {
{ {
return Result.error(loginDTO,"密码错误,登录失败!"); return Result.error(loginDTO,"密码错误,登录失败!");
} }
LoginVO loginVO=new LoginVO(); String LastLogIpLocation = getuser.getLoginIp();
BeanUtil.copyProperties(getuser,loginVO); String IPAddress = ipLocationService.getClientIP(request);
return Result.success(loginVO); String Location = ipLocationService.getIPLocation(IPAddress);
getuser.setLoginIp(Location);
userMapper.UpdateIPLocation(getuser.getEmail(), getuser.getLoginIp());
LoginVO loginVO = new LoginVO();
return Result.success(loginVO,"上次登录IP归属地为" + LastLogIpLocation);
} }
@Override @Override
public Result sendVerificationCode(String email) { public Result sendVerificationCode(String email,HttpServletRequest request) {
//1.校验邮箱是否合法 //1.校验邮箱是否合法
boolean emailInvalid = RegexUtils.isEmailInvalid(email); boolean emailInvalid = RegexUtils.isEmailInvalid(email);
if(emailInvalid){ if(emailInvalid){
@ -121,9 +141,11 @@ public class UserServiceImpl implements UserService {
helper.setTo(email); helper.setTo(email);
helper.setSubject("UniLife - 登录验证码"); helper.setSubject("UniLife - 登录验证码");
String IPAddress = ipLocationService.getClientIP(request);
String Location = ipLocationService.getIPLocation(IPAddress);
String content = "<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #eee; border-radius: 5px;\">" + String content = "<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #eee; border-radius: 5px;\">" +
"<h2 style=\"color: #333;\">您好!</h2>" + "<h2 style=\"color: #333;\">您好!</h2>" +
"<p>感谢您使用UniLife平台您的验证码是:</p>" + "<p>感谢您使用UniLife平台,本次登录地为" + Location + "您的验证码是:</p>" +
"<div style=\"background-color: #f5f5f5; padding: 10px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0;\">" + "<div style=\"background-color: #f5f5f5; padding: 10px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0;\">" +
code + code +
"</div>" + "</div>" +
@ -150,7 +172,7 @@ public class UserServiceImpl implements UserService {
} }
@Override @Override
public Result loginWithEmail(LoginEmailDTO loginEmailDTO) { public Result loginWithEmail(LoginEmailDTO loginEmailDTO,HttpServletRequest request) {
String email=loginEmailDTO.getEmail(); String email=loginEmailDTO.getEmail();
if(RegexUtils.isEmailInvalid(email)){ if(RegexUtils.isEmailInvalid(email)){
@ -174,17 +196,17 @@ public class UserServiceImpl implements UserService {
// 5. 查询用户是否存在 // 5. 查询用户是否存在
User user=userMapper.getUserByEmail(email); User user=userMapper.getUserByEmail(email);
if(user == null){ if(user == null){
user=createUserWithEmail(email); user = createUserWithEmail(email,request);
} }
//6.生成登录凭证 //6.生成登录凭证
String token=jwtUtil.generateToken(user.getId()); //TODO
String token = jwtUtil.generateToken(user.getId());
// 8. 返回用户信息和登录凭证 // 8. 返回用户信息和登录凭证
Map<String, Object> userInfo = new HashMap<>(); Map<String, Object> userInfo = new HashMap<>();
//HashMap userInfo.put("token", token);
userInfo.put("user", user);
userInfo.put("token", token); userInfo.put("token", token);
userInfo.put("user", user);
return Result.success(userInfo); return Result.success(userInfo);
} }
@ -192,14 +214,16 @@ public class UserServiceImpl implements UserService {
/** /**
* 使 * 使
*/ */
private User createUserWithEmail(String email) { private User createUserWithEmail(String email,HttpServletRequest request) {
User user = new User(); User user = new User();
user.setEmail(email); user.setEmail(email);
user.setNickname("用户" + RandomUtil.randomString(6)); // 生成随机昵称 user.setNickname("用户" + RandomUtil.randomString(6)); // 生成随机昵称
String username = email.split("@")[0]+"_"+ RandomUtil.randomString(4); // 使用@前面的部分作为用户名 String username = email.split("@")[0]+"_"+ RandomUtil.randomString(4); // 使用@前面的部分作为用户名
user.setUsername(username); user.setUsername(username);
String password=RandomUtil.randomString(6); String password = RandomUtil.randomString(6);
String IPAddress = ipLocationService.getClientIP(request);
String Location = ipLocationService.getIPLocation(IPAddress);
user.setPassword(password); user.setPassword(password);
user.setRole((byte)0); // 普通用户角色 user.setRole((byte)0); // 普通用户角色
@ -207,7 +231,7 @@ public class UserServiceImpl implements UserService {
user.setIsVerified((byte)0); // 未验证 user.setIsVerified((byte)0); // 未验证
user.setPoints(0); // 初始积分 user.setPoints(0); // 初始积分
user.setGender((byte)0); user.setGender((byte)0);
user.setLoginIp(Location);//注册地IP
// 保存用户 // 保存用户
try { try {
userMapper.insert(user); userMapper.insert(user);

@ -1,10 +1,10 @@
server: server:
port: 8080 port: 8087
spring: spring:
datasource: datasource:
url: jdbc:mysql://localhost:3306/UniLife?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8 url: jdbc:mysql://localhost:3306/UniLife?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
username: root username: root
password: 123456 password: zhong20050428
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
mail: mail:
host: smtp.163.com host: smtp.163.com

@ -11,6 +11,7 @@
<result column="role" property="role"/> <result column="role" property="role"/>
<result column="is_verified" property="isVerified"/> <result column="is_verified" property="isVerified"/>
<result column="status" property="status"/> <result column="status" property="status"/>
<result column="login_ip" property="loginIp"/>
</resultMap> </resultMap>
<insert id="insert" parameterType="com.unilife.model.entity.User" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="com.unilife.model.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users ( INSERT INTO users (
@ -37,11 +38,23 @@
</insert> </insert>
<select id="FindByEmail" resultMap="userResultMap"> <select id="FindByEmail" resultMap="userResultMap">
SELECT id, email, password, username, nickname, avatar, role, is_verified, status SELECT id, email, password, username, nickname, avatar, role, is_verified, status,login_ip
FROM users FROM users
WHERE email = #{email} AND password = #{password} WHERE email = #{email} AND password = #{password}
</select> </select>
<select id="FindByOnlyEmail" resultMap="userResultMap">
SELECT id, email, password, username, nickname, avatar, role, is_verified, status,login_ip
FROM users
WHERE email = #{email}
</select>
<update id="UpdateIPLocation" parameterType="com.unilife.model.entity.User">
UPDATE users
SET login_ip = #{loginIp}
WHERE email = #{email}
</update>
<select id="getUserByEmail" resultType="com.unilife.model.entity.User"> <select id="getUserByEmail" resultType="com.unilife.model.entity.User">
select username, select username,
email, email,

Loading…
Cancel
Save