修改获取真实ip
This commit is contained in:
38
README.md
38
README.md
@@ -13,26 +13,24 @@
|
|||||||
|
|
||||||
## 功能截图
|
## 功能截图
|
||||||
|
|
||||||
### 部门管理
|
<table>
|
||||||

|
<tr>
|
||||||
|
<td><strong>部门管理</strong><br><img src="images/dj_dept.png" alt="部门管理" width="400"></td>
|
||||||
### 用户管理
|
<td><strong>用户管理</strong><br><img src="images/dj_user.png" alt="用户管理" width="400"></td>
|
||||||

|
</tr>
|
||||||
|
<tr>
|
||||||
### 角色管理
|
<td><strong>角色管理</strong><br><img src="images/dj_role.png" alt="角色管理" width="400"></td>
|
||||||

|
<td><strong>岗位管理</strong><br><img src="images/dj_post.png" alt="岗位管理" width="400"></td>
|
||||||
|
</tr>
|
||||||
### 岗位管理
|
<tr>
|
||||||

|
<td><strong>菜单管理</strong><br><img src="images/dj_menu.png" alt="菜单管理" width="400"></td>
|
||||||
|
<td><strong>前端界面</strong><br><img src="images/dj_vue1.png" alt="前端界面" width="400"></td>
|
||||||
### 菜单管理
|
</tr>
|
||||||

|
<tr>
|
||||||
|
<td><strong>权限员工界面</strong><br><img src="images/dj_chenze.png" alt="普通员工界面" width="400"></td>
|
||||||
### 前端界面
|
<td></td>
|
||||||

|
</tr>
|
||||||
|
</table>
|
||||||
### 普通员工界面
|
|
||||||

|
|
||||||
|
|
||||||
# 许可证
|
# 许可证
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
from system.models import User, Menu, LoginLog, Dept
|
from system.models import User, Menu, LoginLog, Dept
|
||||||
|
from utils.ip_utils import get_client_ip
|
||||||
|
|
||||||
from utils.serializers import CustomModelSerializer
|
from utils.serializers import CustomModelSerializer
|
||||||
from utils.custom_model_viewSet import CustomModelViewSet
|
from utils.custom_model_viewSet import CustomModelViewSet
|
||||||
@@ -54,8 +55,12 @@ class UserLogin(ObtainAuthToken):
|
|||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
user = serializer.validated_data['user']
|
user = serializer.validated_data['user']
|
||||||
token, created = Token.objects.get_or_create(user=user)
|
token, created = Token.objects.get_or_create(user=user)
|
||||||
|
|
||||||
|
# 获取真实IP地址
|
||||||
|
client_ip = get_client_ip(request)
|
||||||
|
|
||||||
# 更新登录IP和登录时间
|
# 更新登录IP和登录时间
|
||||||
user.login_ip = request.META.get('REMOTE_ADDR')
|
user.login_ip = client_ip
|
||||||
user.last_login = timezone.now()
|
user.last_login = timezone.now()
|
||||||
user.save(update_fields=['login_ip', 'last_login'])
|
user.save(update_fields=['login_ip', 'last_login'])
|
||||||
user_data = UserSerializer(user).data
|
user_data = UserSerializer(user).data
|
||||||
@@ -63,7 +68,7 @@ class UserLogin(ObtainAuthToken):
|
|||||||
LoginLog.objects.create(
|
LoginLog.objects.create(
|
||||||
username=user.username,
|
username=user.username,
|
||||||
result=LoginLog.LoginResult.SUCCESS,
|
result=LoginLog.LoginResult.SUCCESS,
|
||||||
user_ip=request.META.get('REMOTE_ADDR', ''),
|
user_ip=client_ip,
|
||||||
user_agent=request.META.get('HTTP_USER_AGENT', '')
|
user_agent=request.META.get('HTTP_USER_AGENT', '')
|
||||||
)
|
)
|
||||||
# 在序列化后的数据中加入 accessToken
|
# 在序列化后的数据中加入 accessToken
|
||||||
|
|||||||
73
backend/utils/ip_utils.py
Normal file
73
backend/utils/ip_utils.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
def get_client_ip(request):
|
||||||
|
"""
|
||||||
|
获取客户端真实IP地址
|
||||||
|
考虑代理服务器的情况,按优先级获取IP
|
||||||
|
"""
|
||||||
|
# 按优先级顺序检查各种IP头
|
||||||
|
ip_headers = [
|
||||||
|
'HTTP_X_FORWARDED_FOR', # 最常用的代理IP头
|
||||||
|
'HTTP_X_REAL_IP', # Nginx 代理
|
||||||
|
'HTTP_X_CLIENT_IP', # 客户端IP
|
||||||
|
'HTTP_X_FORWARDED', # 转发IP
|
||||||
|
'HTTP_FORWARDED_FOR', # 标准转发IP
|
||||||
|
'HTTP_FORWARDED', # 标准转发
|
||||||
|
'HTTP_CLIENT_IP', # 客户端IP
|
||||||
|
'REMOTE_ADDR', # 直接连接IP
|
||||||
|
]
|
||||||
|
|
||||||
|
for header in ip_headers:
|
||||||
|
ip = request.META.get(header)
|
||||||
|
if ip:
|
||||||
|
# 处理多个IP的情况(如 X-Forwarded-For: client, proxy1, proxy2)
|
||||||
|
if ',' in ip:
|
||||||
|
# 取第一个IP(客户端真实IP)
|
||||||
|
ip = ip.split(',')[0].strip()
|
||||||
|
|
||||||
|
# 验证IP格式
|
||||||
|
if is_valid_ip(ip):
|
||||||
|
return ip
|
||||||
|
|
||||||
|
# 如果都没有找到,返回 REMOTE_ADDR
|
||||||
|
return request.META.get('REMOTE_ADDR', '')
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_ip(ip):
|
||||||
|
"""
|
||||||
|
验证IP地址格式是否有效
|
||||||
|
"""
|
||||||
|
if not ip:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 简单的IP格式验证
|
||||||
|
parts = ip.split('.')
|
||||||
|
if len(parts) != 4:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
for part in parts:
|
||||||
|
if not 0 <= int(part) <= 255:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_client_ip_simple(request):
|
||||||
|
"""
|
||||||
|
简化版获取客户端IP(推荐用于大多数情况)
|
||||||
|
"""
|
||||||
|
# 优先获取 X-Forwarded-For
|
||||||
|
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||||
|
if x_forwarded_for:
|
||||||
|
# 取第一个IP
|
||||||
|
ip = x_forwarded_for.split(',')[0].strip()
|
||||||
|
if ip:
|
||||||
|
return ip
|
||||||
|
|
||||||
|
# 获取 X-Real-IP
|
||||||
|
x_real_ip = request.META.get('HTTP_X_REAL_IP')
|
||||||
|
if x_real_ip:
|
||||||
|
return x_real_ip
|
||||||
|
|
||||||
|
# 最后使用 REMOTE_ADDR
|
||||||
|
return request.META.get('REMOTE_ADDR', '')
|
||||||
Reference in New Issue
Block a user