The other day, my uncle implemented the REST API in Flask only. With the momentum, I decided to add an authentication function because it was a big deal. I'm an amateur, but when I was researching, I came across basic authentication and Digest authentication. Aside from how it works, I've been able to move the code, so make a note of it.
I referred to the following. (Rather, it's almost the same.)
Also, I think it's best to read the tutorials on the following sites.
-flask_httpauth tutorial:
https://flask-httpauth.readthedocs.io/en/latest/
-requests page:
https://requests-docs-ja.readthedocs.io/en/latest/user/authentication/
It seems to be a method of writing the user name and password as they are in the HTTP request and sending it. On the receiving server side, I used a module called flask_httpauth.
python -m pip install --upgrade pip
python -m pip install flask
python -m pip install flask_httpauth
This is the server-side code used to check the operation. I wonder if there is a more convenient implementation method such as password confirmation, but it worked for the time being, so I will write it down.
server_basicauth.py
from flask import Flask
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
id_list = {
"user001": "password1111",
"user002": "password1234"
}
@auth.get_password
def get_pw(id):
id_list.get(id)
@app.route('/')
@auth.login_required
def index():
return "Hello, %s!" % auth.username()
if __name__ == '__main__':
app.run()
Let's start it for the time being.
$ python server_basicauth.py
* Serving Flask app "server_basicauth" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
You can also implement in python where to send an HTTP request to this server. It seems that there are various modules that can be used, but here we will use requests.
request_basicauth.py
import requests
for pswd in ["password1111", "password2222"]:
usr = "user001"
print("authtication test: user={}, password={}".format(usr, pswd))
r = requests.get('http://localhost:5000/', auth=(usr, pswd))
print("response:", r.status_code)
print(r.content)
print(r.headers)
print("------------------------------------------------------")
If you run it with python request_basicauth.py
in another terminal with the server started, you will get the following result.
authtication test: user=user001, password=password1111
response: 200
b'Hello, user001!'
{'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '15', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:06:21 GMT'}
------------------------------------------------------
authtication test: user=user001, password=password2222
response: 401
b'Unauthorized Access'
{'Content-Type': 'text/html; charset=utf-8', 'Content-Length': '19', 'WWW-Authenticate': 'Basic realm="Authentication Required"', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:06:22 GMT'}
------------------------------------------------------
As expected, the first password will authenticate and return 200, but the next will return 401.
Also, if you enter https: // localhost: 5000
in a browser such as Chrome, you will be asked for the password. When I typed it, Hello user001 was output.
This also worked in the same way. The only difference from Basic authentication is that flask_httpauth uses HTTPDigestAuth.
First, the server side. You will need the private key when you start the server side. Here, it is embedded in the code as it is.
server_httpauth.py
from flask import Flask
from flask_httpauth import HTTPDigestAuth
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key here'
auth = HTTPDigestAuth()
id_list = {
"user001": "password1111",
"user002": "password2222"
}
@auth.get_password
def get_pw(id):
return id_list.get(id)
@app.route('/')
@auth.login_required
def index():
return "Hello, %s!" % auth.username()
if __name__ == '__main__':
app.run()
Similarly, the client side can be implemented with just requests.
request_digestauth.py
import requests
from requests.auth import HTTPDigestAuth
for passwd in ["password1111", "password2222"]:
r = requests.get('http://localhost:5000/', auth=HTTPDigestAuth('user001', passwd))
print(r.status_code)
print(r.headers)
print(r.content)
If you start the server and move the request side in another terminal, it will be as follows.
200
{'Date': 'Sat, 02 Jan 2021 13:22:43 GMT', 'Vary': 'Cookie', 'Content-Length': '15', 'Content-Type': 'text/html; charset=utf-8', 'Server': 'Werkzeug/1.0.1 Python/2.7.17'}
Hello, user001!
401
{'Content-Length': '19', 'Set-Cookie': 'session=.eJyrVkosLcmIz8vPS05VsqpWUkhSslLyC4nK9HWJyvI18qzyzfXLjAxJLo_K9TWNzIrKjgoJy_WtijTyd3c19A93tVWq1YEYkV-QWFiKMCPK3bcqKjwo1x9ojp-Ra3lUVmRVlItTdpRLpIG_S0pGlLtfDsTsdKAZtQAJAC0F.X_Bzow.s0xYY1rqLai75_11dFa7PMOkhck; HttpOnly; Path=/', 'Vary': 'Cookie', 'Server': 'Werkzeug/1.0.1 Python/2.7.17', 'Date': 'Sat, 02 Jan 2021 13:22:43 GMT', 'Content-Type': 'text/html; charset=utf-8', 'WWW-Authenticate': 'Digest realm="Authentication Required",nonce="56b06c3b32cba70fc9b6de5f3668a59a",opaque="dc3edf86c7a0f63d0dd6487adce2cba8"'}
Unauthorized Access
I was able to confirm that if the user name and password are correct, it will be OK, otherwise 401 Unauthorized Access will be returned.
For the time being, I was able to run Basic authentication and Digest authentication.
--There is a lot of information when you read the flask_httpauth page! Various things such as token authentication, role setting, session, server authentication, etc. were written. Can it be used? .. .. --It may be necessary to prepare for CI/CD without raising the private key to github etc. --The user name and password are embedded in the code this time, but when increasing the number of users one by one. .. .. I want to know the general method. ――As for flask in general, what should I do when organizing the code?
There are some things that seem absurd, but today (the second day of the new year) I will leave it around here.
Recommended Posts