我正在为小型项目创建后端服务器(任何安全问题都不是问题)并偶然发现了一个问题。我必须将 JWT 令牌发送到前端,但显然令牌没有到达。这是我的 Flask 服务器的代码:
@app.route('/api/user/login', methods=['POST'])
def login():
cursor = db.cursor()
data = request.get_json()
username = data.get('username')
pw_hash = data.get('pw_hash')
cursor.execute('SELECT pw_hash, id FROM users WHERE username=\'{username}\';')
data = cursor.fetchone()
db.commit()
if data and pw_hash == data[0]:
return jsonify({'token': create_access_token(identity={'id': data[1]})}), 201
return jsonify({'error':'Invalid credentials.'}), 401
这是 React 前端的代码:
import React, { useState } from 'react';
import CryptoJS from 'crypto-js';
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
const payload = {
username: username,
pw_hash: CryptoJS.SHA256(password).toString(),
};
try {
const response = await fetch('/api/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
});
if (response.ok) {
alert('로그인에 성공했습니다.');
localStorage.setItem('token', response.json().token);
} else {
alert('로그인에 실패했습니다.');
}
} catch(error) {
alert('서버 오류');
}
}
return (
<div>
// ...
</div>
);
};
export default Login;
我希望至少能从后端得到一些东西,但是
console.log(reponse.json().token)
返回 undefined
。
感谢您提前的帮助。
编辑:
这是前端的修改代码。
import React, { useState } from 'react';
import CryptoJS from 'crypto-js';
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [data, setData] = useState('');
const handleSubmit = async (e) => {
const payload = {
username: username,
pw_hash: CryptoJS.SHA256(password).toString(),
};
try {
const response = await fetch('/api/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
});
const json = await response.json();
setData(json);
if (response.ok && data) {
alert('로그인에 성공했습니다.');
localStorage.setItem('token', data);
alert(data.token);
} else {
alert('로그인에 실패했습니다.');
}
} catch(error) {
alert('서버 오류');
}
}
return (
<div>
...
</div>
);
};
export default Login;
我根据你的代码写了一个简单的例子。代码修改了两个地方。我认为关键的区别在于数据库查询的代码。您的查询没有为我产生任何结果。
from flask import (
Flask,
current_app,
g,
jsonify,
request
)
from flask_jwt_extended import (
JWTManager,
create_access_token
)
import sqlite3
DATABASE = 'database.db'
app = Flask(__name__)
app.secret_key = 'your secret here'
jwt = JWTManager(app)
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
return db
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
with app.app_context():
try:
db = get_db()
with current_app.open_resource('schema.sql', 'r') as f:
db.executescript(f.read())
db.commit()
except: pass
@app.post('/api/user/login')
def login():
username = request.json.get('username', None)
password = request.json.get('pw_hash', None)
cursor = get_db().cursor()
cursor.execute('SELECT pw_hash, id FROM users WHERE username=?', (username,))
data = cursor.fetchone()
cursor.close()
if data and password == data[0]:
return jsonify({'token': create_access_token(identity={'id': data[1]})}), 201
return jsonify({'error': 'Invalid credentials.'}), 401
import React, { useState } from 'react';
import CryptoJS from 'crypto-js';
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
const payload = {
username: username,
pw_hash: CryptoJS.SHA256(password).toString(),
};
try {
const response = await fetch('/api/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (response.ok && data) {
alert('로그인에 성공했습니다.');
localStorage.setItem('token', data.token);
console.log(data.token);
} else {
alert('로그인에 실패했습니다.');
}
} catch(error) {
console.error('서버 오류');
}
}
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" name="username" onChange={(e) => setUsername(e.target.value)} />
<input type="password" name="password" onChange={(e) => setPassword(e.target.value)} />
<button type="submit">Login</button>
</form>
</div>
);
};
export default Login;