egg之创建登录,注册接口

框架:egg 、umi、antd,mongodb;
mongodb安装教程
egg安装
umi: yarn create @umijs/umi-app;yarn install;yarn start;umi bulid;
初步步骤就完成了

egg

  1. 安装相应的插件;
    →config/plugin.js
  // 跨域
  cors: {
    enable: true,
    package: 'egg-cors',
  },
  // mongodb 数据库
  mongoose: {
    enable: true, // 开启插件
    package: 'egg-mongoose',
  },
  //  鉴权
  jwt: {
    enable: true,
    package: 'egg-jwt',
  },
  1. 配置
    →config/config.default.js
config.security = {
    csrf: {
      enable: false,
      ignoreJSON: true,
    },
    // domainWhiteList: [ '*' ], // []中放放出的白名单,*代表所有
  };
  // 白名单 domainWhiteList: ['127.0.0.1:8080']
  // 配置跨域 config.cors = { origin: 'http:127.0.0.1:8080'
  // 匹配规则 域名+端口 *则为全匹配 allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH', credentials: true };
  config.cors = {
    origin: '*',
    allowMethods: 'GET,HEAD,PUT,OPTIONS,POST,DELETE,PATCH',
    credentials: true,
  };
  // 配置访问地址
  config.cluster = {
    listen: {
      path: '',
      port: 3000,
      hostname: '192.168.1.1', // ip地址
    },
  };
  // config中配置mongoose连接mongodb数据库
  // Mongodb://eggadmin:123456@localhost:27017 //有用户名密码的情况
  // user 数据库名称
  config.mongoose = {
    client: {
      url: 'mongodb://127.0.0.1:27017/user',
      options: {
        useNewUrlParser: true,
      },
    },
  };
  // 鉴权 生成token
  config.jwt = {
    secret: '123456', // 自定义token的加密条件字符串,可按各自的需求填写
    ignore: ['/api/registered', '/api/login'], // 哪些请求不需要认证
    // enable: true, // default is false
    // match: '/jwt', // optional
    expiresIn: '24h',
  };
  1. 创建数据模型 →app/model/user.js
'use strict';
module.exports = app => {
  const mongoose = app.mongoose;
  // 定义数据库的结构
  const Schema = mongoose.Schema;
  // 按照mock的数据,字段:name/password id自动生成
  const UserSchema = new Schema({
    // _id: {
    //   type: Number,
    // },
    username: {
      type: String,
    },
    password: {
      type: String,
    },
    lastTime: {
      type: Number,
    },
    token: {
      type: String,
    },
    role: {
      type: String,
    },
    dsc: {
      type: String,
    },
  });
  // 映射到egg-mongo db 库的user表中(不区分大小写)
  const User = mongoose.model('users', UserSchema);
  // 方法放到这里
  initUserData(User);
  return User;
};
// Entity 可以绑定具体数据对Model实例化
function initUserData(User) {
  // 查询数据库
  User.find({}, (err, doc) => {
    if (err) {
      console.log(err);
      console.log('创建用户失败');
    } else if (!doc.length) {
      new User({
        username: 'admin',
        password: '123456',
        role: 'admin',
        dsc: '拥有系统内所有菜单和路由权限',
        lastTime: Date.now(),
      }).save();
    } else {
      console.log('-------------创建用户成功--------------');
    }
  });
}

先打开navicat连接数据库 检查是否连接上,运行项目后会发现自动创建数据表,打开表有数据说明添加成功了;
在这里插入图片描述
4. 注册
控制器:app/controller/user.js

'use strict';
/** 控制器 */
const Controller = require('egg').Controller;

class IndexController extends Controller {
  /** 注册 */
  * registered() {
    const params = yield this.ctx.request.body;
    yield this.ctx.service.user.registered(params);
  }
}
module.exports = IndexController;

服务器: 主要用来做逻辑判断,app/service/user.js

'use strict';
const Service = require('egg').Service;
class IndexService extends Service {
  // 注册
  * registered(params) {
    // 注册判断是否存在
    const corr = yield this.ctx.model.User.findOne({ username: params.username });
    params.role = 'user';
    if (!corr) {
      yield this.ctx.model.User.insertMany([ params ]);
      this.ctx.body = '注册成功';
    } else {
      this.ctx.body = '该用户名已注册';
    }
  }
}
module.exports = IndexService;
  1. 路由 app/router.js
'use strict';
module.exports = app => {
  const { router, controller, jwt } = app; // jwt 后续会用到做token验证
  router.post('/api/registered', controller.user.registered); // 注册
};

添加用户成功
添加用户成功
登录

  1. 控制器:app/controller/user.js
  /** 登录 */
  * login() {
    const params = yield this.ctx.request.body;
    yield this.ctx.service.user.login(params);
  }
  1. app/service/user.js
// 登录
  * login(params) {
    const { ctx, app } = this;
    const corr = yield ctx.model.User.findOne({ username: params.username });
    // 用户是否存在
    if (!corr) {
      this.ctx.body = '用户名错误';
    } else {
      if (params.password === corr.password) {
        // 生成Token
        const Token = app.jwt.sign({
          username: params.username,	// 需要存储的Token数据
        }, app.config.jwt.secret, {
          expiresIn: '1800s', // 有效期时间
        });
        // token 存储至数据库中
        yield ctx.model.User.updateOne({ username: params.username }, { token: Token }, { multi: true });
        const user = yield ctx.model.User.findOne({ username: params.username });
        // 将生成的Token返回给前端
        ctx.body = user;
      } else {
        this.ctx.body = '密码错误,请重新输入!';
      }
    }
  }
  1. 路由 app/router.js
'use strict';
module.exports = app => {
  const { router, controller, jwt } = app; // jwt 后续会用到做token验证
 router.post('/api/registered', controller.user.registered); // 注册
  router.post('/api/login', controller.user.login); // 登录并生成Token
};

antd

code:

models/user.ts

import { Effect, Reducer } from 'umi';
import { setToken } from '@/utils/localToken';
import { ResponseData } from '@/pages/data';
import { accountLogin, accountRegistered } from '@/services/user';

/**
 * 用户state状态
 */
export interface CurrentUser {
    _id: number;
    username: string;
    roles: string[];
}

export interface UserModelState {
    currentUser: CurrentUser;
    message: number;
    loginStatus: string
}

export interface ModelType {
    namespace: string;
    state: UserModelState;
    effects: {
        login: Effect;
        register: Effect;
    };
    reducers: {
        changeLoginStatus: Reducer<string>;
    };
}

const initState: UserModelState = {
    currentUser: {
        _id: 0,
        username: '',
        roles: [],
    },
    message: 0,
    loginStatus: 'ok',
};

const Model: ModelType = {
    namespace: 'user',
    state: initState,
    effects: {
        // 登录
        *login({ payload }, { call, put }) {
            let status = undefined;
            try {
                // 获取token
                const response: ResponseData = yield call(accountLogin, payload);
                const { token, role, username } = response;
                // 存储本地Token
                yield call(setToken, token || '');
                status = 'ok';
            } catch (error) {
                if (error.message && error.message === 'CustomError') {
                    status = 'error';
                }
            }
            yield put({ type: 'changeLoginStatus', payload: status, });
            if (status === 'ok') { return true; } else if (status === 'error') { return false; }
            return undefined;
        },

        // 注册
        *register({ payload }, { call, put }) {
            let status = undefined;
            try {
                const msg = yield call(accountRegistered, payload);
                status = msg;
            } catch (error) {
                status = 'error';
            }
            if (status === 'error') { return false; }
            return status;
        },
    },
    reducers: {
        changeLoginStatus(state: any, { payload }) {
            return {
                ...initState,
                ...state,
                loginStatus: payload,
            };
        },
    }
};
export default Model;

pages/login/index.ts

import React, { useState } from 'react';
import { connect } from 'dva'
import { Dispatch, Link, useIntl, history, useModel } from 'umi';
import styles from './index.less';
import { UserModelState } from '@/models/user';
import { Form, Input, Button, Alert, message } from 'antd';
import { UserOutlined, UnlockOutlined } from '@ant-design/icons';
import { LoginParamsType } from '@/pages/data.d';
/**
 * 登录页
 */
interface LoginProps {
    userLogin: UserModelState;
    submitLoading?: boolean;
    dispatch: Dispatch;
    location: Location & { query: any };
}
const Login: React.FC<LoginProps> = props => {
    const { userLogin, submitLoading, dispatch, location } = props;
    const { query } = location;
    const { redirect } = query;
    const { loginStatus } = userLogin;
    const { formatMessage } = useIntl();
    const [loginForm] = Form.useForm();
    const [formName, setFormName] = useState('login');

    // 登录
    const handleSubmit = async (values: any) => {
        if (formName === 'login') {
            const res: boolean = await dispatch({
                type: 'user/login',
                payload: values[formName],
            });
            if (res === true) {
                message.success('登录成功!');
                history.replace(redirect || '/');
            }
        } else {
            const res: boolean = await dispatch({
                type: 'user/register',
                payload: values[formName],
            });
            message.success(res);
        }

    };

    // 表单组件
    const FormItemComponents = (props: any) => {
        const { name } = props;
        return (<>
            <h1 className={styles.title}>
                {name === 'login' ? '账户登录' : '账户注册'}
            </h1>
            <Form name="basic" onFinish={handleSubmit} initialValues={{}} form={loginForm}>
                <Form.Item
                    label=""
                    name={[name, "username"]}
                    rules={[{ required: true, message: '请输入用户名', },]}
                >
                    <Input placeholder={'用户名: admin or test or user'} prefix={<UserOutlined />} />
                </Form.Item>

                <Form.Item
                    label=""
                    rules={[{ required: true, message: '请输入密码', },]}
                    name={[name, 'password']}
                >
                    <Input.Password
                        placeholder={'密码:123456'}
                        prefix={<UnlockOutlined />}
                    />
                </Form.Item>

                {
                    name === 'login' ? null : <Form.Item
                        label=""
                        name={[name, 'rePassword']}
                        dependencies={['password']}
                        hasFeedback
                        rules={[
                            {
                                required: true,
                                message: '请确认密码!',
                            },
                            ({ getFieldValue }) => ({
                                validator(_, value) {
                                    if (!value || getFieldValue([name, 'password']) === value) {
                                        return Promise.resolve();
                                    }

                                    return Promise.reject(new Error('您输入的两个密码不匹配!'));
                                },
                            }),
                        ]}
                    >
                        <Input.Password placeholder={'确认密码'} prefix={<UnlockOutlined />} />
                    </Form.Item>
                }

                <Form.Item>
                    <Button
                        type="primary"
                        className={styles.submit}
                        htmlType="submit"
                        loading={submitLoading}
                    >
                        {name === 'login' ? '登录' : ' 注册'}
                    </Button>
                </Form.Item>
                <div className={styles['text-align-right']} onClick={registerClickedHandler}>
                    {name === 'login' ? ' 还没有账户?现在注册!' : '现在就去登录!'}
                </div>
                {loginStatus === 'error' && !submitLoading && (
                    <Alert
                        message={'用户名或密码错误!'}
                        type="error"
                        showIcon
                    />
                )}
            </Form>
        </>
        )
    }
    // 切换注册
    const registerClickedHandler = () => {
        if (formName === 'login') {
            setFormName('register')
        } else {
            setFormName('login')
        }
        loginForm.resetFields();
    }
    return (
        <div className={styles.main}>
            <FormItemComponents name={formName} />
        </div>
    );
};


export default connect(({ user, loading }: {
    user: UserModelState; loading: {
        effects: {
            [key: string]: boolean;
        };
    }
}) => ({
    userLogin: user,
    submitLoading: loading.effects['userLogin/login'],
}))(Login);

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值