1. 程式人生 > >CSRF LOG 郵箱配置及使用

CSRF LOG 郵箱配置及使用

Django的csrf中介軟體

CSRF:跨站請求偽造Cross Site Request Forgery

CSRF的攻擊流程

使用者a 訪問可信站點1做業務處理,此時瀏覽器會儲存該網站的cookie,當用戶a 訪問不可信站點2時,如果站點2有指向站點1的連結時候,那麼攻擊就用可能發生

Eg:

1、包含站點1的連結,點選跳轉

2、img 的src屬性值是站點1的連結

3、Js載入,js裡有跳轉的動作

Django的解決方法

Django預防CSRF攻擊的方法是在使用者提交的表單中加入一個csrftoken的隱含值,這個值和伺服器中儲存的csrftoken的值相同

前後端的使用

後端

全域性使用(禁用)

使用中介軟體操作

區域性使用或禁用

from django.views.decorators.csrf import csrf_exempt(不使用CSRF驗證), csrf_protect(使用CSRF校驗)

前端

Form表單

{%csrf_token%}

Ajax 方式

<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>

<script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>


function submit() {
    {#    拿資料#}
        var name = $("#name").val();
        var num = $("#num").val();
        var csrf_token = $.cookie("csrftoken");
        console.log(csrf_token);
        $.ajax({
            url:"/t08/cz",
            data:{
                "name": name,
                "num": num,
                "csrfmiddlewaretoken": csrf_token
            },
            method:"post",
            success: function (res) {
                console.log(res);
            }
        })
    }

使用: 後端

全域性使用(禁用)

使用中介軟體操作

區域性使用或禁用

from django.views.decorators.csrf import csrf_exempt(不使用CSRF驗證), 

csrf_protect(使用CSRF校驗)

前端

Form表單

{%csrf_token%}

Ajax  方式

LOG

Log簡介

logging模組是Python內建的標準模組,主要用於輸出執行日誌,可以設定輸出日誌的等級、日誌儲存路徑、日誌檔案回滾等;相比print,具備如下優點:

通過log的分析,可以方便使用者瞭解系統或軟體、應用的執行情況;如果你的應用log足夠豐富,也可以分析以往使用者的操作行為、型別喜好、地域分佈或其他更多資訊;如果一個應用的log同時也分了多個級別,那麼可以很輕易地分析得到該應用的健康狀況,及時發現問題並快速定位、解決問題,補救損失。

Log的用途

不管是使用何種程式語言,日誌輸出幾乎無處不再。總結起來,日誌大致有以下幾種用途:

  • 問題追蹤:通過日誌不僅僅包括我們程式的一些bug,也可以在安裝配置時,通過日誌可以發現問題。
  • 狀態監控:通過實時分析日誌,可以監控系統的執行狀態,做到早發現問題、早處理問題。
  • 安全審計:審計主要體現在安全上,通過對日誌進行分析,可以發現是否存在非授權的操作

Log等級

  • DEBUG最詳細的日誌資訊,典型應用場景是 問題診斷
  • INFO資訊詳細程度僅次於DEBUG,通常只記錄關鍵節點資訊,用於確認一切都是按照我們預期的那樣進行工作
  • WARNING當某些不期望的事情發生時記錄的資訊(如,磁碟可用空間較低),但是此時應用程式還是正常執行的
  • ERROR由於一個更嚴重的問題導致某些功能不能正常執行時記錄的資訊 如IO操作失敗或者連線問題
  • CRITICAL當發生嚴重錯誤,導致應用程式不能繼續執行時記錄的資訊

Log模組的四大元件

  • Loggers
    提供應用程式程式碼直接使用的介面

  • Handlers
    用於將日誌記錄傳送到指定的目的位置

    FileHandler:logging.FileHandler;日誌輸出到檔案
    RotatingHandler:logging.handlers.RotatingHandler;日誌回滾方式,支援日誌檔案最大數量和日誌檔案回滾
    SMTPHandler:logging.handlers.SMTPHandler;遠端輸出日誌到郵件地址
    HTTPHandler:logging.handlers.HTTPHandler;通過"GET"或者"POST"遠端輸出到HTTP伺服器
    等等
    
  • Filters
    提供更細粒度的日誌過濾功能,用於決定哪些日誌記錄將會被輸出(其它的日誌記錄將會被忽略)

  • Formatters
    用於控制日誌資訊的最終輸出格式

    %(levelno)s:列印日誌級別的數值
    %(levelname)s:列印日誌級別的名稱
    %(pathname)s:列印當前執行程式的路徑,其實就是sys.argv[0]
    %(filename)s:列印當前執行程式名
    %(funcName)s:列印日誌的當前函式
    %(lineno)d:列印日誌的當前行號
    %(asctime)s:列印日誌的時間
    %(thread)d:列印執行緒ID
    %(threadName)s:列印執行緒名稱
    %(process)d:列印程序ID
    %(message)s:列印日誌資訊
    

示例

  import logging
  logger = logging.getLogger(__name__) 
  logger.setLevel(level = logging.INFO)
  handler = logging.FileHandler(“log.txt”) 
  formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  handler.setFormatter(formatter) 
  logger.addHandler(handler) 

  logger.info("Start print log")
  logger.debug("Do something")
  logger.warning("Something maybe fail.")
  logger.info("Finish")

Django中的配置

  ADMINS = (
   ('tom','*******@163.com'),
  )
  EMAIL_BACKEND ='django.core.mail.backends.smtp.EmailBackend'
  SERVER_EMAIL=EMAIL_HOST_USER


	#####可自定義修改
  LOGGING = {
   'version': 1,
   'disable_existing_loggers': True,
   'formatters': {
   'standard': {
    'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'} 
   },
   'filters': {
   'require_debug_false': {
    '()': 'django.utils.log.RequireDebugFalse',
    }
   },
   'handlers': {
   'null': {
    'level': 'DEBUG',
    'class': 'logging.NullHandler',
   },
   'mail_admins': {
    'level': 'ERROR',
    'class': 'django.utils.log.AdminEmailHandler',
    'filters': ['require_debug_false'],
   },
   'debug': {
    'level':'DEBUG',
    'class':'logging.handlers.RotatingFileHandler',
    'filename': os.path.join(BASE_DIR, "log",'debug.log'), #檔案路徑
    'maxBytes':1024*1024*5, 
    'backupCount': 5,
    'formatter':'standard',
   },
   'console':{
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'standard',
   },
   },
   'loggers': {
   'django': {
    'handlers': ['console'],
    'level': 'DEBUG',
    'propagate': False
   },
   'django.request': {
    'handlers': ['debug','mail_admins'],
    'level': 'ERROR',
    'propagate': True,是否繼承父類的log資訊
   },
   # 對於不在 ALLOWED_HOSTS 中的請求不傳送報錯郵件
   'django.security.DisallowedHost': {
    'handlers': ['null'],
    'propagate': False,
   },
   } 
  }


  import logging
  logger = logging.getLogger("django") # 為loggers中定義的名稱
  logger.info("some info...")

自定義修改

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'
        },
        'easy':{
            'format': '%(asctime)s|%(funcName)s|%(message)s'
        }
    },
    'filters': { #過濾條件
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true':{
            '()': 'django.utils.log.RequireDebugTrue', #邀要求debug是True
        }
    },
    'handlers': {
        'mail_admins': {  #一旦線上程式碼報錯 郵件提示
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['require_debug_false'],
        },
        'debug': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(BASE_DIR, "log", 'debug.log'),  # 檔案路徑
            'maxBytes': 1024 * 1024 * 5, #5兆的資料
            'backupCount': 5, #允許有5這樣的檔案
            'formatter': 'easy', #格式
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'standard',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'debug'],
            'level': 'DEBUG',
            'propagate': False
        },
        'django.request': {
            'handlers': ['debug', 'mail_admins'],
            'level': 'ERROR',
            'propagate': True, #是否繼承父類的log資訊
        },
        # 對於不在 ALLOWED_HOSTS 中的請求不傳送報錯郵件
        'django.security.DisallowedHost': {
            'handlers': ['debug'],
            'propagate': False,
        },
    }
}

郵箱

配置

EMAIL_USE_SSL = True

EMAIL_HOST = 'smtp.qq.com'  # 如果是 163 改成 smtp.163.com

EMAIL_PORT = 465

EMAIL_HOST_USER = environ.get("EMAIL_SENDER") # 帳號

EMAIL_HOST_PASSWORD = environ.get("EMAIL_PWD")  # 授權碼(****)

DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

注意:郵箱要開啟smtp服務 並且記錄授權碼

https://docs.djangoproject.com/zh-hans/2.0/topics/email/

修改setting.py 加入郵箱配置
EMAIL_USE_SSL = True

EMAIL_HOST = 'smtp.qq.com'  # 如果是 163 改成 smtp.163.com

EMAIL_PORT = 465

EMAIL_HOST_USER = "[email protected]" # 帳號

EMAIL_HOST_PASSWORD = "xxxxx"  # 授權碼(****)

DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

views裡使用

普通單封郵件
def send_my_mail(req):
    title = "阿里offer"
    message = "恭喜您 成為我們公司CEO"
    email_from = "[email protected]"
    #收件者
    recs = ["[email protected]", "[email protected]", "[email protected]"]
    #傳送郵件
    send_mail(title, message, email_from, recs)
    return HttpResponse("CEO開始嗨起來")

多封普通郵件的傳送
def send_emailss(req):
    title1 = "騰訊offer"
    message1 = "恭喜您 被騙了"
    email_from = "[email protected]"
    title2 = "這是一封挑事的郵件"
    message2 = "大哥大哥別殺我"
    recs1 = ["[email protected]",
            "[email protected]",
            "[email protected]"]
    recs2 = ["[email protected]",
             "[email protected]",
             "[email protected]",
             "[email protected]"]
    senders1 = (title1, message1, email_from, recs1)
    senders2 = (title2, message2, email_from, recs2)
    send_mass_mail((senders1, senders2), fail_silently=False)
    return HttpResponse("OK")

send_mail和send_mass_mail的區別

send_mail每次都連線SMTP服務

send_mass_mail 連一次就可以發多個

傳送html的郵件

def email_html(req):
    title = "阿里offer"
    message = "恭喜您 成為我們公司CEO"
    email_from = "[email protected]"
    recs = [
            "[email protected]",

            ]
    html_content = '<a href={url}>{url}</a>'.format(url=url)

    msg = EmailMultiAlternatives(title,message, email_from, recs)
    msg.attach_alternative(html_content, "text/html")
    msg.send()
    return HttpResponse("OK")

郵箱驗證碼

	1 生成驗證碼

	2 準備郵件內容 拼接驗證url

	3 傳送郵件

	4 拿到url裡的那個token

	5 改變郵箱對應使用者的狀態

生成驗證連線傳送郵件

from django.core.mail import send_mail
from django.http import HttpResponse
from django.shortcuts import render
from email_verfiry import myutil
from django.core.cache import cache
# Create your views here.
def get_verify_code(req):
    param = req.GET
    email = param.get('email')
    name = param.get('name')
    #驗證郵箱書寫規則合法性
    #驗證這個郵箱是否在我們的系統註冊過了

    #生成驗證碼
    token = myutil.get_token()
    #拼接驗證連線
    verify_url = "https://www.baidu.com//verify/" + token
    # 儲存驗證碼
    cache.set(token, email, 60)
    # 傳送郵件
    title = "歡迎註冊會員"
    message = "請將如下連線 複製到瀏覽器訪問{url}".format(
        url=verify_url
    )
    email_from = "[email protected]"
    send_mail(title, message, email_from, [email])
    return HttpResponse("註冊成功,請檢視啟用郵件")

驗證url的正確性

def verify(req, token):
    email = cache.get(token)
    if email:
     	# 去資料庫找Email對應人
        return HttpResponse("修改使用者狀態,可以使用"+email)
    else:
        return HttpResponse("驗證連結不正確")