1. 思路
第一步:
前端页面向后端发送生成csrf请求(get 方法),后端服务器生成csrf_token返回gei前端
第二步:
前端收到csrf_token后,将csrf_token写入cookie中,在post请求中,随cookie与请求头发送到后端中。
2.相关代码
2.1 Nginx 配置
## # You should look at the following URL's in order to grasp a solid understanding # of Nginx configuration files in order to fully unleash the power of Nginx. # https://www.nginx.com/resources/wiki/start/ # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ # https://wiki.debian.org/Nginx/DirectoryStructure # # In most cases, administrators will remove this file from sites-enabled/ and # leave it as reference inside of sites-available where it will continue to be # updated by the nginx packaging team. # # This file will automatically load configuration files provided by other # applications, such as Drupal or Wordpress. These applications will be made # available underneath a path with that package name, such as /drupal8. # # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. ## # Default server configuration # #server { # listen 80 default_server; # listen [::]:80 default_server; # SSL configuration # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf; # root /var/www/html; # Add index.php to the list if you are using PHP # index index.html index.htm index.nginx-debian.html; # server_name _; # location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. # try_files $uri $uri/ =404; # } # pass PHP scripts to FastCGI server # #location ~ .php$ { # include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): # fastcgi_pass unix:/run/php/php7.3-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /.ht { # deny all; #} #} # Virtual Host configuration for example.com # # You can move that to a different file under sites-available/ and symlink that # to sites-enabled/ to enable it. # server { listen 80; listen [::]:80; # server_name localhost; # #root /var/www/example.com; # root /var/www/html; # root /home/pi/Desktop/tornado_example/linux_tornado/movie/static; # index index.html; # location ~* /admin/ { # try_files $uri $uri/ =404; proxy_pass http://127.0.0.1:5000; # proxy_connect_timeout 600; # proxy_read_timeout 600; proxy_cookie_domain localhost:5000 localhost:80; #保证cookie不受跨域影响 } location / { root /var/www/; index index.nginx-debian.html; } location /html/ { root /var/www/static/; index index.nginx-debian.html; } }
2.1 flask 后端编写
from flask_wtf import csrf @admin.route("/csrf_token") def get_csrf_token(): "生成csrf_token" csrf_token = csrf.generate_csrf() return '{"errno":0,"errmsg":"OK","csrf_token":"%s"}' % csrf_token,200,{"Content-Type":"application/json"}
2.2 前端编写
js 文件
login.js
function getCookie(name) { var r = document.cookie.match("\b" + name + "=([^;]*)\b"); return r ? r[1] : undefined; } function setCookie() { $.get("/admin/csrf_token",function(resp) { // 向后端发送获取csrf_token 请求 $("#csrf_token").attr("csrf_token",resp.csrf_token) // 将得到的 csrf_token写道html元素中 }); } $(document).ready(function() { $("#user").focus(function(){ $("#user-err").hide(); }); $("#password").focus(function(){ $("#password-err").hide(); }); setCookie() //获取csrf_token $(".form-login").submit(function(e){ e.preventDefault(); account = $("#user").val(); passwd = $("#password").val(); if (!account) { $("#user-err span").html("请填写正确帐号!"); $("#user-err").show(); return; } if (!passwd) { $("#password-err span").html("请填写密码!"); $("#password-err").show(); return; } var data = { account:account, password:passwd }; var csrf_data = $("#csrf_token").attr("csrf_token"); // 从html 获取csrf_token document.cookie = "csrf_token" + "=" + csrf_data; // 将csrf_token 写入cookie var jsonData = JSON.stringify(data); $.ajax({ // post 请求登录 url:"/admin/sessions", type:"post", data:jsonData, contentType:"application/json", dataType:"json", headers:{ "X-CSRFToken":getCookie("csrf_token") }, success:function (data) { if (data.errno=="0"){ // 登录成功,跳转到主页 location.href ="/html/index.html" } else { // 其他错误信息,在页面中展示 $("#password-err span").html(data.errmsg); $("#password-err").show(); } } }); }); })
html 文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>招投标爬虫管理</title> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <link rel="stylesheet" href="../static/admin/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="../static/fonts/css/font-awesome.min.css"> <link rel="stylesheet" href="../static/ionicons/css/ionicons.min.css"> <link rel="stylesheet" href="../static/admin/dist/css/AdminLTE.min.css"> <link rel="stylesheet" href="../static/admin/plugins/iCheck/square/blue.css"> </head> <body class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <a href=""><b>招投标爬虫系统</b></a> </div> <div class="login-box-body"> <p class="login-box-msg"></p> <form class="form-login"> <div class="form-group has-feedback"> <input name="user" id="user" type="text" class="form-control" placeholder="请输入账号!"> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> <div class="col-md-12" id="input_user"></div> </div> <div class="error-msg" id="user-err"><i class="fa fa-exclamation-circle"></i><span></span></div> <div class="form-group has-feedback"> <input name="pwd" id="password" type="password" class="form-control" placeholder="请输入密码!"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> <div class="col-md-12" id="input_pwd"></div> </div> <div class="error-msg" id="password-err"><i class="fa fa-exclamation-circle"></i><span></span></div> <div class="form-group has-feedback"> <input name="csrf_token" id="csrf_token" type="hidden" class="form-control" > </div> <div class="row"> <div class="col-xs-8"></div> <div class="col-xs-4"> <input id="btn-sub" type="submit" class="btn btn-primary btn-block btn-flat" value="登录"> </div> </div> </form> </div> </div> <script src="../static/admin/plugins/jQuery/jQuery-2.2.0.min.js"></script> <script src="../static/admin/bootstrap/js/bootstrap.min.js"></script> <script src="../static/admin/plugins/iCheck/icheck.min.js"></script> <script src="/static/js/crawler/login.js"></script> </body> </html>