トークンベースの認証
5367 ワード
ユーザー認証方法は次のとおりです.
サーバベースの認証と
トークンベースの認証方法があります.
トークンベースの認証方式を実現してみました.
(サーバベースの認証も実施)
ログイン時にサーバがトークンを生成し,クライアントがトークンを受信し,ログイン時に一人で使用できるapiのみを許可するプロセスをコードで簡単に記録する.
インストール済みライブラリ
Flask==2.0.2
pymongo==3.12.1
pyjwt==2.3.0
目次ログイン後、サーバ上でトークンを作成し、クライアントにトークン を提供する.クライアントストレージトークン(jwt)の2つの方法
(Cookie,localstorage=(1),(2) に保存)
利用可能なapiを実現するにはログインが必要です
(クライアントがCookieに保存されている場合、localstorageが保存されている場合)
= (1), (2))
(現時点(2)未実施)
推測1)fetchとrender template部分があまり一致しない
推測2)最初にタイトルを変更するgetリクエストは不可能である.
3-(2).
サーバベースの認証と
トークンベースの認証方法があります.
トークンベースの認証方式を実現してみました.
(サーバベースの認証も実施)
ログイン時にサーバがトークンを生成し,クライアントがトークンを受信し,ログイン時に一人で使用できるapiのみを許可するプロセスをコードで簡単に記録する.
インストール済みライブラリ
Flask==2.0.2
pymongo==3.12.1
pyjwt==2.3.0
目次
(Cookie,localstorage=(1),(2)
利用可能なapiを実現するには
(クライアントがCookieに保存されている場合、localstorageが保存されている場合)
= (1), (2))
(現時点(2)未実施)
#로그인시 토큰생성api
@app.route('/api/login', methods=['POST'])
def token_maker():
#post방식으로 request시에만 등록
if request.method == 'POST':
#로그인 페이지에서 유저가 쓴 email, password받음
email = request.form['email']
pw = request.form['password']
#유저 비밀번호 암호화
pw_encrypt = hashlib.sha256(pw.encode('utf-8')).hexdigest()
#로그인 페이지에서 유저가 쓴 email, password를 데이터베이스에서 확인
findingResult = db.userInfo.find_one({'email': email, 'password': pw_encrypt}, {'_id': False})
#데이터베이스에 유저가 쓴 email과 password가 있을시 토큰생성
if findingResult:
#토큰의 payload식별자는 유저정보중 중복되지 않는 email로하고 토큰만료시간은 600초로 설정
payload = {'id': email,
#쿠키사용시에는 exp를 프론트에서 설정
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=600)}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
#생성된 토큰과 메세지 json형식으로 클라이언트로 response
return jsonify({'token': token, 'msg': 'success'})
#데이터베이스에 유저가 쓴 email과 password가 없을 시 토큰생성실패
return jsonify({'msg': 'Not available'})
2-(1).//로그인 창에 이메일 비밀번호 누르면 실행되는 함수
async function login_info() {
const email = inputId.value;
const pw = inputPw.value;
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: `email=${email}&password=${pw}`,
};
const response = await fetch("/api/login", options);
const result = await response.json();
//서버에서 로그인이 성공시
if (result["msg"] == "success") {
// jwt를 쿠키에 저장
document.cookie = `mytoken=${result["token"]}`;
alert("환영합니다!");
// 메인페이지로 이동
window.location.href = "/home";
//서버에서 로그인 실패시
} else {
alert("ID와 비밀번호를 확인해주세요");
}
}
2-(2).const inputId = document.querySelector('#input_id')
const inputPw = document.querySelector('#input_pw')
//로그인 창에 이메일 비밀번호 누르면 실행되는 함수
async function login_info() {
const email = inputId.value;
const pw = inputPw.value;
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: `email=${email}&password=${pw}`,
};
const response = await fetch("/api/login", options)
const result = await response.json();
//서버에서 로그인이 성공시
if (result['msg'] == 'success'){
//jwt를 localStorage에 저장
localStorage.setItem('jwt', result['token'])
alert('환영합니다!');
//localStorage에 있던 jwt 가져옴
const token = localStorage.getItem('jwt')
//jwt header에 포함
const homeOptions = {
method: "GET",
headers: {
"jwt":token
}
};
// 메인 페이지를 열기 위한 ajax요청
// fetch("/home", homeOptions)
//서버에서 로그인 실패시
}else{
alert('ID와 비밀번호를 확인해주세요')
}
}
3-(1).#로그인을 해야 열리는 메인페이지
@app.route('/home')
def home():
#http request의 header의 cookie를 받음
token_receive = request.cookies.get('mytoken')
#쿠키가 있을시 메인페이즈를 열어주고 payload에서 받은 유저의 이메일을 통해 유저식별
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
user_info = db.userInfo.find_one({"email": payload['id']})
return render_template('index.html', user_info=user_info)
#쿠키가 없을시 로그인페이지로
except jwt.ExpiredSignatureError:
return redirect(url_for("login"))
except jwt.exceptions.DecodeError:
return redirect(url_for("login"))
まず許可されていないコード:推測1)fetchとrender template部分があまり一致しない
推測2)最初にタイトルを変更するgetリクエストは不可能である.
3-(2).
#로그인을 해야 열리는 메인페이지
@app.route('/home')
def home():
#http request의 header의 jwt를 받음
token_receive = request.headers.get('jwt')
#헤더에 jwt가 있을시 메인페이즈를 열어주고 payload에서 받은 유저의 이메일을 통해 유저식별
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
user_info = db.userInfo.find_one({"email": payload['id']})
return render_template('index.html', user_info=user_info)
#헤더에 jwt가 없을시 로그인페이지로
except jwt.ExpiredSignatureError:
return redirect(url_for("login"))
except jwt.exceptions.DecodeError:
return redirect(url_for("login"))
Reference
この問題について(トークンベースの認証), 我々は、より多くの情報をここで見つけました https://velog.io/@golddong98/토큰-기반-인증テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol