Explorar el Código

secure_transport

ignatz hace 4 años
padre
commit
6136a7290a
Se han modificado 15 ficheros con 139 adiciones y 56 borrados
  1. 11 20
      account/decorators.py
  2. 15 7
      account/views.py
  3. BIN
      db.sqlite3
  4. 2 11
      docs/account.md
  5. 0 0
      docs/file.md
  6. 0 0
      docs/folder.md
  7. 7 1
      docs/group.md
  8. 7 3
      file/views.py
  9. 10 5
      folder/views.py
  10. 1 1
      group/models.py
  11. 12 6
      group/views.py
  12. 15 0
      private.rsa
  13. 0 0
      public.rsa
  14. 57 1
      utils/crypto.py
  15. 2 1
      utils/debug.py

+ 11 - 20
account/decorators.py

@@ -4,22 +4,8 @@ from .models import User
 from utils.http import make_json_response
 from utils.http import make_json_response
 
 
 
 
-def user_passes_test(test_func, error):
-    def decorator(view_func):
-        @wraps(view_func)
-        def _wrapped_view(request, *args, **kwargs):
-            if test_func(request):
-                return view_func(request, *args, **kwargs)
-            return make_json_response(code=401, error=error)
-        return _wrapped_view
-    return decorator
-
-
-def login_required(function=None, error='未登录'):
-    """
-    Decorator for views that checks that the _user is logged in, redirecting
-    to the log-in page if necessary.
-    """
+def login_required(error='未登录'):
+    # 判断是否登录的decorator
     def is_login(request):
     def is_login(request):
         if request.method != 'POST':
         if request.method != 'POST':
             return False
             return False
@@ -39,7 +25,12 @@ def login_required(function=None, error='未登录'):
             request.user = user
             request.user = user
         return True
         return True
 
 
-    actual_decorator = user_passes_test(is_login, error)
-    if function:
-        return actual_decorator(function)
-    return actual_decorator
+    def decorator(view_func):
+        @wraps(view_func)
+        def _wrapped_view(request, *args, **kwargs):
+            if is_login(request):
+                return view_func(request, *args, **kwargs)
+            return make_json_response(code=401, error=error)
+        return _wrapped_view
+
+    return decorator

+ 15 - 7
account/views.py

@@ -5,7 +5,8 @@ from django.shortcuts import render
 from datetime import datetime, time
 from datetime import datetime, time
 from .models import User, LoginToken
 from .models import User, LoginToken
 from django.http import JsonResponse
 from django.http import JsonResponse
-from utils.decorators import debug_view
+from utils.debug import debug_view
+from utils.crypto import secure_transport
 from utils.http import make_json_response
 from utils.http import make_json_response
 from .models import get_user
 from .models import get_user
 from django.views.decorators.http import require_POST
 from django.views.decorators.http import require_POST
@@ -20,7 +21,8 @@ def auth_with_username_or_email(username, password):
     return user
     return user
 
 
 
 
-@debug_view('username', 'password', 'email')
+@secure_transport
+@debug_view('password', 'email')
 @require_POST
 @require_POST
 def register(request):
 def register(request):
     username = request.POST.get('username', '')
     username = request.POST.get('username', '')
@@ -43,7 +45,8 @@ def register(request):
         return make_json_response(code=500, error=str(e))
         return make_json_response(code=500, error=str(e))
 
 
 
 
-@debug_view('username', 'password')
+@secure_transport
+@debug_view('password')
 @require_POST
 @require_POST
 def login(request):
 def login(request):
     username = request.POST.get('username', '')
     username = request.POST.get('username', '')
@@ -81,7 +84,8 @@ def login(request):
     return make_json_response(token=token)
     return make_json_response(token=token)
 
 
 
 
-@debug_view('username', 'token')
+@secure_transport
+@debug_view()
 @login_required
 @login_required
 def logout(request):
 def logout(request):
     user = get_user(request)
     user = get_user(request)
@@ -92,7 +96,8 @@ def logout(request):
     return make_json_response()
     return make_json_response()
 
 
 
 
-@debug_view('username', 'email')
+@secure_transport
+@debug_view('email')
 @require_POST
 @require_POST
 def send_email_verification_code(request):
 def send_email_verification_code(request):
     data = request.POST
     data = request.POST
@@ -115,12 +120,14 @@ def send_email_verification_code(request):
         return make_json_response(code=500, error='验证码发送失败')
         return make_json_response(code=500, error='验证码发送失败')
 
 
 
 
-@debug_view('username', 'token')
+@secure_transport
+@debug_view()
 @require_POST
 @require_POST
 def check_token(request):
 def check_token(request):
     data = request.POST
     data = request.POST
     username = data.get('username')
     username = data.get('username')
     token = data.get('token')
     token = data.get('token')
+    print(username)
     try:
     try:
         user = User.objects.get(username=username)
         user = User.objects.get(username=username)
     except:
     except:
@@ -133,7 +140,8 @@ def check_token(request):
         return make_json_response(code=303, error='验证码无效')
         return make_json_response(code=303, error='验证码无效')
 
 
 
 
-@debug_view('username', 'password', 'token')
+@secure_transport
+@debug_view('password')
 @require_POST
 @require_POST
 def reset_password(request):
 def reset_password(request):
     data = request.POST
     data = request.POST

BIN
db.sqlite3


+ 2 - 11
account/api.md → docs/account.md

@@ -42,16 +42,7 @@
 
 
 ## reset_password
 ## reset_password
 ### params
 ### params
-'username', 'email', 'token'
+'username', 'password', 'token'
 ### return
 ### return
 - code=302, error='用户不存在'
 - code=302, error='用户不存在'
-- code=301, error='邮箱错误'
-- code=500, error='验证码发送失败'
-
-## check_token
-### params
-'username', 'token'
-### return
-- code=302, error='用户不存在'
-- code=303, error='验证码无效'
-- code=200
+- code=303, error='验证码无效'

+ 0 - 0
file/api.md → docs/file.md


+ 0 - 0
folder/api.md → docs/folder.md


+ 7 - 1
group/group.md → docs/group.md

@@ -32,4 +32,10 @@
 - code=401, error='未登录'
 - code=401, error='未登录'
 - code=403, error='群不存在'
 - code=403, error='群不存在'
 - code=421, error='群主不可退群'
 - code=421, error='群主不可退群'
-- code=200
+- code=200
+
+## group_list
+### params
+'username', 'token'
+### return
+- code=200, group_list

+ 7 - 3
file/views.py

@@ -8,15 +8,17 @@ from .judgement_function import judge_filepath, format_size
 from django.utils.http import urlquote
 from django.utils.http import urlquote
 import os
 import os
 from account.models import get_user
 from account.models import get_user
-from utils.decorators import debug_view
+from utils.debug import debug_view
 from utils.http import make_json_response
 from utils.http import make_json_response
 from utils.permission import can_delete
 from utils.permission import can_delete
+from utils.crypto import secure_transport
 
 
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 
 # Create your views here.
 # Create your views here.
 
 
 
 
+@secure_transport
 @debug_view(template_name='upload_file.html')
 @debug_view(template_name='upload_file.html')
 @login_required
 @login_required
 def upload_file(request):
 def upload_file(request):
@@ -56,7 +58,8 @@ def upload_file(request):
     return make_json_response()
     return make_json_response()
 
 
 
 
-@debug_view('username', 'token', 'file_id')
+@secure_transport
+@debug_view('file_id')
 @login_required
 @login_required
 def download_file(request):
 def download_file(request):
     user = get_user(request)
     user = get_user(request)
@@ -76,7 +79,8 @@ def download_file(request):
     return response
     return response
 
 
 
 
-@debug_view('username', 'token', 'file_id')
+@secure_transport
+@debug_view('file_id')
 @login_required
 @login_required
 def delete_file(request):
 def delete_file(request):
     data = request.POST
     data = request.POST

+ 10 - 5
folder/views.py

@@ -1,14 +1,16 @@
 from account.decorators import login_required
 from account.decorators import login_required
 from .models import Folder
 from .models import Folder
 from account.models import get_user
 from account.models import get_user
-from utils.decorators import debug_view
+from utils.debug import debug_view
 from utils.http import make_json_response
 from utils.http import make_json_response
 from utils.permission import can_delete
 from utils.permission import can_delete
+from utils.crypto import secure_transport
 
 
 # Create your views here.
 # Create your views here.
 
 
 
 
-@debug_view('username', 'token')
+@secure_transport
+@debug_view()
 @login_required
 @login_required
 def get_root_folder(request):
 def get_root_folder(request):
     # 获取根目录
     # 获取根目录
@@ -17,7 +19,8 @@ def get_root_folder(request):
 
 
 
 
 # 在根目录下列出所有文件夹与文件
 # 在根目录下列出所有文件夹与文件
-@debug_view('username', 'token', 'folder_id')
+@secure_transport
+@debug_view('folder_id')
 @login_required
 @login_required
 def folder_list(request):
 def folder_list(request):
     data = request.POST
     data = request.POST
@@ -37,7 +40,8 @@ def folder_list(request):
 
 
 
 
 # 增文件夹
 # 增文件夹
-@debug_view('username', 'token', 'father_folder_id', 'folder_name')
+@secure_transport
+@debug_view('father_folder_id', 'folder_name')
 @login_required
 @login_required
 def add_folder(request):
 def add_folder(request):
     data = request.POST
     data = request.POST
@@ -61,7 +65,8 @@ def add_folder(request):
 
 
 
 
 # 删除文件夹
 # 删除文件夹
-@debug_view('username', 'token', 'folder_id')
+@secure_transport
+@debug_view('folder_id')
 @login_required
 @login_required
 def delete_folder(request):
 def delete_folder(request):
     data = request.POST
     data = request.POST

+ 1 - 1
group/models.py

@@ -31,5 +31,5 @@ class Group(models.Model):
 # 信号接收函数,每当新建Group实例的时候自动调用
 # 信号接收函数,每当新建Group实例的时候自动调用
 @receiver(post_save, sender=Group)
 @receiver(post_save, sender=Group)
 def add_creator_to_group_members(sender, instance, created, **kwargs):
 def add_creator_to_group_members(sender, instance, created, **kwargs):
-    if created and instance.creator not in instance.members:
+    if created and not instance.members.filter(username=instance.creator.username):
         instance.members.add(instance.creator)
         instance.members.add(instance.creator)

+ 12 - 6
group/views.py

@@ -1,13 +1,15 @@
 from account.decorators import login_required
 from account.decorators import login_required
 from .models import Group
 from .models import Group
 from account.models import User, get_user
 from account.models import User, get_user
-from utils.decorators import debug_view
+from utils.debug import debug_view
 from utils.http import make_json_response
 from utils.http import make_json_response
+from utils.crypto import secure_transport
 
 
 # Create your views here.
 # Create your views here.
 
 
 
 
-@debug_view('username', 'token', 'group_id')
+@secure_transport
+@debug_view('group_id')
 @login_required
 @login_required
 def get_group_root_folder(request):
 def get_group_root_folder(request):
     user = get_user(request)
     user = get_user(request)
@@ -21,7 +23,8 @@ def get_group_root_folder(request):
     return make_json_response(root_folder_id=root_folder.folder_id)
     return make_json_response(root_folder_id=root_folder.folder_id)
 
 
 
 
-@debug_view('username', 'token', 'group_id')
+@secure_transport
+@debug_view('group_id')
 @login_required
 @login_required
 def join_group(request):
 def join_group(request):
     user = get_user(request)
     user = get_user(request)
@@ -38,7 +41,8 @@ def join_group(request):
     return make_json_response()
     return make_json_response()
 
 
 
 
-@debug_view('username', 'token', 'group_name')
+@secure_transport
+@debug_view('group_name')
 @login_required
 @login_required
 def create_group(request):
 def create_group(request):
     user = get_user(request)
     user = get_user(request)
@@ -51,7 +55,8 @@ def create_group(request):
     return make_json_response()
     return make_json_response()
 
 
 
 
-@debug_view('username', 'token', 'group_id')
+@secure_transport
+@debug_view('group_id')
 @login_required
 @login_required
 def quit_group(request):
 def quit_group(request):
     user = get_user(request)
     user = get_user(request)
@@ -69,7 +74,8 @@ def quit_group(request):
 
 
 
 
 # 获取你所在的所有群组
 # 获取你所在的所有群组
-@debug_view('username', 'token')
+@secure_transport
+@debug_view()
 @login_required
 @login_required
 def group_list(request):
 def group_list(request):
     user = get_user(request)
     user = get_user(request)

+ 15 - 0
private.rsa

@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCRQZ5O/AOAjeYAaSFf6Rjhqovws78I716I9oGF7WxCIPmcaUa1
+YuyLOncCCuPsaw69+RMWjdbOBp8hd4PPM/d4mKTOVEYUE0SfxhhDTZaM5CzQEUXU
+yXy7icQTGR5wBjrbjU1yHCKOf5PJJZZQWB06husSFZ40TdL7FdlBpZ1u1QIDAQAB
+AoGATKE/cQ/GkTVK14Ce2MhSFgsxFGTfLUmKp9rT7eGZMTHQPVHUubBcdf779Znl
+MD4yYspZ5ZYickJQBQnWAaO6s5om/Pt0PBFNzAz/WzZaccQtYKOe/6v022splsjp
+N6StlV2l/vL0JpZYEWTEEYtiRQR1aHqdX9ce5UrH9k6YqYECQQDSZTvlA5sp3PV/
+9WHa1WgzouKO4N8PbtXlavQdNflpJQD9278SKAUSPex5Qzyh8fgmV3jg8dcY9MTz
+itx1M+RRAkEAsL3WoDz7Vh4R8dG6Dxf7OGa01CB9OGn7nj1LsCk0EEYo55dHm9on
+QXtM9lQB9brT6bP6eEqbk9xyNzySfDJVRQJABcqbl3Y98y0N5PPQOcHeGG3HZr9x
+5G7cnHARQCyYLPjDyjkeTVWkrhfeRog/RwXuGsAVp7uAfENgmIOeBevjwQJASjYL
+7pBsgEZ0BnOnijrpk08c0o0pxwxJSLI4G6nRYJv1BPkyajB5lzcso6m2gPWHkXOu
+0d+R384Kb0MRxvBjeQJBAMUijpXwAlAkPwmSaLxEzJmlA2rOOt4W61M56e9bkTJP
+ET+w2P5QZxhjHlHnmSyFSuV9jYHKfZyUEilghraZ3y0=
+-----END RSA PRIVATE KEY-----

+ 0 - 0
utils/public.rsa → public.rsa


+ 57 - 1
utils/crypto.py

@@ -1,18 +1,74 @@
-from Crypto import Random
+import base64
+
 from Crypto.PublicKey import RSA
 from Crypto.PublicKey import RSA
 from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
 from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
+from Crypto.Cipher import AES
+from functools import wraps
+from utils.http import make_json_response
+import json
 
 
+IV = '16-Bytes--String'
 
 
 with open('public.rsa') as f:
 with open('public.rsa') as f:
     key = f.read()
     key = f.read()
     public_key = RSA.import_key(key)
     public_key = RSA.import_key(key)
     public_cipher = PKCS1_cipher.new(public_key)
     public_cipher = PKCS1_cipher.new(public_key)
+    print(public_key.exportKey().decode(encoding='utf-8'))
 
 
 with open('private.rsa') as f:
 with open('private.rsa') as f:
     key = f.read()
     key = f.read()
     private_key = RSA.import_key(key)
     private_key = RSA.import_key(key)
     private_cipher = PKCS1_cipher.new(private_key)
     private_cipher = PKCS1_cipher.new(private_key)
+    # print(private_key.exportKey().decode(encoding='utf-8'))
+
+
+# 安全传输decorator
+def secure_transport(view_func):
+    @wraps(view_func)
+    def _wrapped_view(request, *args, **kwargs):
+        data = request.POST
+        enc_key = data.get('enc_key')
+        cipher_text = data.get('cipher_text')
+        if not enc_key or not cipher_text:
+            print('无加密')
+            return view_func(request, *args, **kwargs)
+        aes_key = private_cipher.decrypt(base64.b64decode(enc_key.encode('utf-8')), b'error').decode('utf-8')
+        print(f'key={aes_key}')
+
+        aes_cipher = AES.new(aes_key.encode('utf-8'), AES.MODE_CBC, IV.encode('utf-8'))
+        decrypted = aes_cipher.decrypt(base64.b64decode(cipher_text.encode('utf-8')))
+        # print(decrypted)
+        decrypted = decrypted[:-decrypted[-1]]
+        # print(decrypted)
+        plain_text = decrypted.decode('utf-8')
+        print(plain_text)
+
+        loaded = json.loads(plain_text)
+        dec_request = request
+        dec_request.POST = {**request.POST, **loaded}
+
+        raw_response = view_func(dec_request, *args, **kwargs)
+
+        content = raw_response.content
+        padding = 16 - len(content) % 16
+        content += bytes([padding] * padding)
+        print(content)
+
+        aes_cipher = AES.new(aes_key.encode('utf-8'), AES.MODE_CBC, IV.encode('utf-8'))
+        enc_content = base64.b64encode(aes_cipher.encrypt(content)).decode('utf-8')
+        print(enc_content)
+        return make_json_response(enc_content=enc_content)
+    return _wrapped_view
+
+
+def test():
+    plain_text = '{"username": "user1"}'
+    encrypted = public_cipher.encrypt(bytes(plain_text.encode('utf8')))
+    cipher_text = base64.b64encode(encrypted)
+    print(cipher_text.decode('utf8'))
 
 
+    decrypted = private_cipher.decrypt(base64.b64decode(cipher_text), b'error')
+    print(decrypted.decode('utf8'))
 
 
 # print(public_key.exportKey().decode('utf-8'))
 # print(public_key.exportKey().decode('utf-8'))
 
 

+ 2 - 1
utils/decorators.py → utils/debug.py

@@ -6,6 +6,7 @@ from django.shortcuts import render
 from django.http import JsonResponse
 from django.http import JsonResponse
 
 
 DEBUG = settings.DEBUG
 DEBUG = settings.DEBUG
+DEFAULT_ITEMS = ['username', 'token', 'enc_key', 'cipher_text']
 
 
 
 
 def debug_view(*items, template_name='debug.html'):
 def debug_view(*items, template_name='debug.html'):
@@ -14,7 +15,7 @@ def debug_view(*items, template_name='debug.html'):
         def _wrapped_view(request, *args, **kwargs):
         def _wrapped_view(request, *args, **kwargs):
             if DEBUG and request.method == 'GET':
             if DEBUG and request.method == 'GET':
                 print('render debug view')
                 print('render debug view')
-                return render(request, template_name, {'items': items})
+                return render(request, template_name, {'items': [*items, *DEFAULT_ITEMS]})
             else:
             else:
                 return view_func(request, *args, **kwargs)
                 return view_func(request, *args, **kwargs)
         return _wrapped_view
         return _wrapped_view