GrammyLi / bbs

论坛
0 stars 0 forks source link

【登录相关】 #1

Open GrammyLi opened 4 months ago

GrammyLi commented 4 months ago
from flask import Flask, request, jsonify, session, make_response
from flask_cors import CORS
from flask_session import Session
from models.user import User
import jwt
import datetime

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SESSION_TYPE'] = 'filesystem'

# Initialize extensions
CORS(app, supports_credentials=True)
Session(app)

def generate_token(user_id):
    payload = {
        'user_id': user_id,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(days=30)
    }
    token = jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')
    return token

def verify_token(token):
    try:
        payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        return payload['user_id']
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

@main.route("/login", methods=['POST'])
def login():
    form = request.get_json()
    print("form", form)
    u = User.validate_login(form)
    print('login user <{}>'.format(u))
    if u is None:
        response = make_response(jsonify({'msg': '登录失败', "code": 201}))
    else:
        token = generate_token(u.id)
        response = make_response(jsonify({'msg': '登录成功', "code": 200, "data": u.to_dict(), "token": token}))

    return response

@main.route("/protected", methods=['GET'])
def protected():
    token = request.headers.get('Authorization')
    if token:
        user_id = verify_token(token)
        if user_id:
            return jsonify({'msg': '已登录', 'user_id': user_id})
        else:
            return jsonify({'msg': '令牌无效或已过期'}), 401
    else:
        return jsonify({'msg': '未提供令牌'}), 401

if __name__ == '__main__':
    app.run(debug=True)
import axios from 'axios';
import { message } from 'antd';

axios.defaults.withCredentials = true; // 确保带上 Cookie

const setAuthToken = (token) => {
  if (token) {
    axios.defaults.headers.common['Authorization'] = token;
  } else {
    delete axios.defaults.headers.common['Authorization'];
  }
};

export const login = async (data: { username: string; password: string }) => {
  try {
    const response = await axios.post("http://127.0.0.1:5000/login", data, {
      headers: {
        'Content-Type': 'application/json',
      },
    });
    console.log("response", response);
    return response.data;
  } catch (error) {
    console.error("Error during login:", error);
    throw error;
  }
};

const fetchProtectedResource = async () => {
  try {
    const response = await axios.get("http://127.0.0.1:5000/protected");
    console.log("Protected resource:", response.data);
  } catch (error) {
    console.error("Error fetching protected resource:", error);
  }
};

const onFinish = async (values: any) => {
  console.log("Received values of form: ", values);
  try {
    const data = await login({
      username: values.username,
      password: values.password,
    });
    message.success("登录成功");
    setAuthToken(data.token);
    fetchProtectedResource(); // 获取受保护资源
    onClose();
  } catch (error) {
    message.error("登录失败,请检查用户名和密码");
  }
};

// 在组件中调用
const AuthModal: React.FC<AuthModalProps> = ({ visible, onClose }) => {
  const [form] = Form.useForm();

  return (
    <Modal
      title="登录/注册"
      visible={visible}
      onCancel={onClose}
      footer={null}
    >
      <Tabs defaultActiveKey="1" centered>
        <TabPane tab="登录" key="1">
          <Form
            form={form}
            name="login"
            onFinish={onFinish}
            initialValues={{ remember: true }}
          >
            <Form.Item
              name="username"
              rules={[{ required: true, message: '请输入用户名!' }]}
            >
              <Input prefix={<UserOutlined />} placeholder="用户名" />
            </Form.Item>
            <Form.Item
              name="password"
              rules={[{ required: true, message: '请输入密码!' }]}
            >
              <Input
                prefix={<LockOutlined />}
                type="password"
                placeholder="密码"
              />
            </Form.Item>
            <Form.Item>
              <Button type="primary" htmlType="submit" className="auth-modal__button">
                登录
              </Button>
            </Form.Item>
          </Form>
        </TabPane>
        <TabPane tab="注册" key="2">
          <Form
            form={form}
            name="register"
            onFinish={onFinish}
          >
            <Form.Item
              name="username"
              rules={[{ required: true, message: '请输入用户名!' }]}
            >
              <Input prefix={<UserOutlined />} placeholder="用户名" />
            </Form.Item>
            <Form.Item
              name="password"
              rules={[{ required: true, message: '请输入密码!' }]}
            >
              <Input
                prefix={<LockOutlined />}
                type="password"
                placeholder="密码"
              />
            </Form.Item>
            <Form.Item>
              <Button type="primary" htmlType="submit" className="auth-modal__button">
                注册
              </Button>
            </Form.Item>
          </Form>
        </TabPane>
      </Tabs>
    </Modal>
  );
};

export default AuthModal;

验证流程 启动 Flask 服务器。 在浏览器中访问前端页面。 通过前端页面登录,检查响应中是否包含 token。 在前端保存 token 并设置 Authorization 头。 发送后续请求,确认请求头中包含 Authorization,并且后端可以正确识别这些令牌。 通过这些步骤,你可以确保前端在登录后正确存储和发送 JWT 令牌,后端可以识别这些令牌并进行身份验证