2, Django uses the jinja2 template
2.1 jinja2 introduction
Jinja2: it is the next widely used template engine in Python. It is a template language implemented by python. Its design idea comes from Django's template engine and extends its syntax and a series of powerful functions, especially the built-in template language in Flask framework
Because Django's default template engine is not fully functional and slow, we can also use jinja2 in Django. Jinja2 claims to be 10-20 times faster than Django's default template engine.
Django's mainstream third-party apps basically support Django's default template and jinja2 at the same time, so there won't be many obstacles to using jinja2.
[jinja2 template has no multiline comments]
2.2 installing jinja2 modules
pip install jinja2
2.3 Django configuration
- Create jinja2 in the project file_ env. Py file
from jinja2 import Environment def environment(**options): env = Environment(**options) return env
2. In settings Py file
TEMPLATES = [ { 'BACKEND': 'django.template.backends.jinja2.Jinja2',#Amendment 1 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS':True, 'OPTIONS':{ 'environment': 'jinja2_env.environment',# Revision 2 'context_processors':[ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
2.4 most jinja2 templates are the same as Django's own templates
2.5 jinja2 custom filters
Django documentation: https://docs.djangoproject.com/en/1.11/topics/templates/#module-django.template.backends.django
In jinja2_ env. Custom filter in py file
from jinja2 import Environment def environment(**options): env = Environment(**options) # 2. Add a custom filter to the environment env.filters['do_listreverse'] = do_listreverse return env # 1. Custom filter def do_listreverse(li): if li == "B": return "ha-ha"
3, CSRF
- CSRF is spelled as Cross Site Request Forgery and translated as cross site request forgery.
- CSRF means that an attacker embezzles your identity and sends malicious requests in your name.
- Including: sending emails, sending messages, stealing your account, even buying goods, virtual currency transfer
- Problems: personal privacy disclosure and property security.
3.1 schematic diagram of CSRF attack
- The client does not perform security verification with the server when accessing the server
3.2 preventing CSRF attacks
step
- When the client requests interface data from the back-end, the back-end will set CSRF in the cookie in the response_ Value of token
- Add a hidden field in the Form, and the value is also csrf_token
- When the user clicks submit, it will bring these two values to make a request to the background
- The backend receives the request to the following events:
- Remove CSRF from cookie_ token
- Remove the hidden CSRF from the form data_ Value of token
- Compare
- If the two values are the same after comparison, it means that it is a normal request. If it is not obtained or the comparison is different, it means that it is not a normal request and the next operation is not performed
3.3 code demonstration
WebA without csrf verification
- Backend code implementation
#Define route from django.conf.urls import url from pay import views urlpatterns = [ url(r'^$',views.LoginView.as_view(),name='index'), #Login routing url(r'^transfer/$',views.TransferView.as_view(),name='transfer'), #Transfer route ] #Define view class LoginView(View): def post(self,request): # Get the parameters submitted in the form username = request.POST.get("username") password = request.POST.get("password") if not all([username, password]): print('Parameter error') else: print(username, password) if username == 'laowang' and password == '1234': # The status is maintained. Setting the user name into the cookie indicates successful login response = redirect(reverse('transfer')) response.set_cookie('username', username) return response else: print('Password error') return render(request,'login.html') def get(self,request): return render(request,'login.html') class TransferView(View): def post(self,request): # Get user name from cookie username = request.COOKIES.get('username', None) # If you don't get it, it means you don't log in if not username: return redirect(reverse('index')) to_account = request.POST.get("to_account") money = request.POST.get("money") print('Pretend to perform transfer operation and transfer the money of the currently logged in user to the specified account') return HttpResponse('transfer accounts %s Yuan Dao %s success' % (money, to_account)) def get(self, request): # Render conversion page response = render(request, 'transfer.html') return response
- Front end login page code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Sign in</title> </head> <body> <h1>I'm a website A,Login page</h1> <form method="post"> <label>user name:</label><input type="text" name="username" placeholder="enter one user name"><br/> <label>password:</label><input type="password" name="password" placeholder="Please input a password"><br/> <input type="submit" value="Sign in"> </form> </body> </html>
- Front end transfer page code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>transfer accounts</title> </head> <body> <h1>I'm a website A,Transfer page</h1> <form method="post"> <label>Account:</label><input type="text" name="to_account" placeholder="Please enter the account to transfer"><br/> <label>amount of money:</label><input type="number" name="money" placeholder="Please enter the transfer amount"><br/> <input type="submit" value="transfer accounts"> </form> </body> </html>
Run the test. If you cannot directly enter the transfer page without logging in, the test transfer is successful
Code to attack website B
- Backend code implementation
#Define route from django.conf.urls import url from ads import views urlpatterns = [ url(r'^$',views.AdsView.as_view()), ] #Define view class AdsView(View): def get(self,request): return render(request,'index.html')
- Front end code implementation
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>I'm a website B</h1> <form method="post" action="http://127.0.0.1:9000/transfer/"> <input type="hidden" name="to_account" value="hacker"> <input type="hidden" name="money" value="190000" hidden> <input type="submit" value="Click to receive the coupon"> </form> </body> </html>
Run the test. When the user logs in to website A, click the button of website B to realize forged access
3.4 implement CSRF in website A_ Token verification process
- Import generated csrf_token function
from django.middleware.csrf import get_token csrf_token = get_token(request)
-
In rendering the transfer page, do the following:
- Generate CSRF_ Value of token
- Set CSRF in the response returned to the transfer page_ Token into cookie
- CSRF_ The token is saved in the hidden field of the form
def get(self, request): # Generate csrf_token from django.middleware.csrf import get_token csrf_token = get_token(request) # Render conversion page, pass in csrf_token into template response = render(request, 'transfer.html',context={'csrf_token':csrf_token}) # Set CSRF_ The token is stored in the cookie for submitting verification response.set_cookie('csrf_token', csrf_token) return response
-
Add CSRF to the transfer template form_ Token hidden field
<head> <meta charset="UTF-8"> <title>transfer accounts</title> </head> <body> <h1>I'm a website A,Transfer page</h1> <form method="post"> <input type="hidden" name="csrftoken" value="{{ csrf_token }}"> <label>Account:</label><input type="text" name="to_account" placeholder="Please enter opposite account"><br/> <label>amount of money:</label><input type="number" name="money" placeholder="Please enter the transfer amount"><br/> <input type="submit" value="transfer accounts"> </form> </body> </html>
Run the test. After entering the transfer page, view the cookie and html source code
- Perform CSRF before executing the transfer logic_ Verification of token
# Remove the CSRF from the form_ token form_csrf_token = request.POST.get("csrftoken") # Remove the CSRF from the cookie_ token cookie_csrf_token = request.COOKIES.get('csrf_token') # Compare if cookie_csrf_token != form_csrf_token: return HttpResponse('token Verification failed. It may be an illegal operation')
After running the test, the user has no problem operating directly on website A, and then goes to website B for operation. It is found that the transfer is unsuccessful because website B cannot obtain the CSRF in the form_ The hidden field of token, and the browser has the same origin strategy. Website B cannot obtain the cookie of website A, so the problem of Cross Site Request Forgery is solved
3.5 solve CSRF attack in Django project
Django turns on CSRF by default
Set CSRF token in template
{% csrf_token %} perhaps <input type="hidden" value="{{ csrf_token }}">