pyx / sanic-wtf Goto Github PK
View Code? Open in Web Editor NEWSanic meets WTForms
License: Other
Sanic meets WTForms
License: Other
Hi there. Can someone tell me how to add csrf token on an ajax request i tried adding a "X-CSRF-TOKEN" header. But it still shows "CSRF token missing"
Since it is not just me using it now, I leave this here, just for the record, and for publicity.
Like I said in the source code, the current mechanism the CSRF works is because there is a registered middleware to change Form.Meta.csrf_context
to the current request session at the beginning of request handling, and because of the thread-sharing nature of async style, I can think of the possibility of an await
or yield from
happened before the form.validate()
call, will that change the session? I still did not wrap my head around about that...
I have this weird design due to avoidance of explicitly passing in the current request object each time we use the form, is it really a good idea?
Comments, suggestions, criticisms are welcome.
As of version 0.3.0, I changed hidden_tag
into more in line with Flask-WTF
's, which includes all hidden tags in addition to the csrf_token. This sounds good except I did not wrap the whole thing inside Markup
and returned a string directly, which broke the API.
In stead of having yet another dependency (markupsafe), I am planning to remove property hidden_tag
, the token will still be accessible as form.csrf_token
or whatever name user set in configuration anyway. I may add it back later on if there will be strong demand.
Are there any plans for supporting them?
Sanic 20.3.0 doesn't support item assignment.
lines like request['session'] = session
should be replaced with request.ctx.session = session
It's a good practice to check referrer header as well.
Will add that if I have time.
Please add support for submitting CSRF tokens in headers like Flask-WTF. See here: https://github.com/lepture/flask-wtf/blob/master/flask_wtf/csrf.py
I need to access the CSRF token in the client side is so I could use a rest API to use the website. It would be helpful to be able to access the CSRF in the request handler just like you can in flask-wtforms
import os
from datetime import datetime
from sanic import Sanic
from sanic.exceptions import NotFound
from sanic_useragent import SanicUserAgent
from sanic_compress import Compress
from sanic.response import file, html, redirect
from sanic_session import InMemorySessionInterface
from sanic_jinja2 import SanicJinja2
from sanic_wtf import SanicWTF
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, Length
app = Sanic(__name__)
jinja = SanicJinja2(app)
wtf = SanicWTF(app)
Compress(app)
session = InMemorySessionInterface(expiry=600)
SanicUserAgent.init_app(app, default_locale='en_US')
app.config['SECRET_KEY'] = os.urandom(24)
@app.middleware('request')
async def add_session_to_request(request):
await session.open(request)
@app.middleware('response')
async def save_session(request, response):
await session.save(request, response)
@app.exception(NotFound)
async def ignore_404s(request, exception):
page = dict()
page['title'] = '404 Error'
page['header'] = '404 Error - Page Not Found'
page['text'] = 'We Can\'t Seem To Find ' + request.url
return jinja.render('page.html', request, page=page)
async def index(request):
return jinja.render('index.html', request)
async def images(request, name):
return await file('images/' + name)
async def styles(request):
return await file('css/styles.css')
async def admin_styles(request):
return await file('css/admin.css')
async def post(request):
return jinja.render('post.html', request, postname='Default')
async def dashboard(request):
cookie_check = request.cookies.get('session')
if cookie_check is not None:
return jinja.render('admin.html', request, pagename='Dashboard')
else:
return redirect('login')
async def login(request):
page = dict()
if request.method == 'POST':
get_email = request.form.get('email')
get_password = request.form.get('password')
if get_email == "[email protected]" and get_password == "12345":
request['session']['username'] = get_email
page['title'] = 'Login'
page['header'] = 'Thank you for logging in!'
page['text'] = 'Redirecting in 3 seconds...'
return jinja.render('page.html', request, page=page,
js_head_end='<script defer>window.setTimeout(function(){ window.location = "admin"; },3000);</script>')
cookie_check = request.cookies.get('session')
if cookie_check is None:
page['title'] = 'Login'
page['header'] = 'Restricted Area - Login Required'
page['text'] = '<form role="form" method="POST">' \
'<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">' \
'<input class="mdl-textfield__input" type="email" id="user" name="email">' \
'<label class="mdl-textfield__label" for="user">Email address</label></div>' \
'<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">' \
'<input class="mdl-textfield__input" type="password" id="password" name="password">' \
'<label class="mdl-textfield__label" for="password">Password</label></div>' \
'<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">Login</button>' \
'</form>'
return jinja.render('page.html', request, page=page)
page['title'] = 'Login'
page['header'] = 'You\'re already logged in!'
page['text'] = 'Redirecting in 3 seconds...'
return jinja.render('page.html', request, page=page,
js_head_end='<script defer>window.setTimeout(function(){ window.location = "/"; },3000);</script>')
async def logout(request):
return html('<h1>Logging out %s</h1>' % request['session'])
async def redirect_index(request):
return redirect('/')
app.add_route(index, '/')
app.add_route(images, 'images/<name>')
app.add_route(styles, 'styles.css')
app.add_route(admin_styles, 'admin.css')
app.add_route(post, 'post.html')
app.add_route(dashboard, 'admin')
app.add_route(login, 'login', methods=['GET', 'POST'])
app.add_route(logout, 'logout')
app.add_route(redirect_index, '/index.html')
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8000, debug=True)
https://gist.github.com/stopspazzing/92bf288e56deb6a8ce8a943bc61442e4
I try to run guestbook; and it is working fine until I set workers=4, because my machine is a 4-core monster; and nightmare starts to come.
expected results
form can be always submitted without error
what really happens
Sometimes form is submitted successfully, and sometimes not. I print out form.errors, and see that, the error is "csrf failed"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.