Skip to content

Commit 1e69e3f

Browse files
Hokori23upupming
andauthored
feat: 用户登录接口 /api/user/login (#4)
* feat: 用户登录接口 /api/user/login * feat: 错误码枚举 * feat: 错误处理中间件 & jwt错误码 & jwt测试用例 * feat: 用户查询接口 * fix(tinyfix): 删除冗余代码 * fix: 解决jsonwebtoken ts类型问题 * feat: 添加checkJWT, refreshJWT中间件 & 抽出token有效期配置 * fix: 处理review comment & 移除了refreshJWT中间件 * feat: add dotenv Co-authored-by: upupming <[email protected]>
1 parent 2d563b3 commit 1e69e3f

19 files changed

+1180
-1164
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ yarn-error.log
99
build
1010
storybook-static
1111
.vercel
12+
.env

backend/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# ByteDance 7 后端代码
2+
3+
## dotenv 配置
4+
5+
项目使用 `dotenv` 存储秘钥等信息,你需要在此目录下创建一个 `.env 文件,并且存储如下的秘钥:
6+
7+
```env
8+
ACCESS_TOKEN_SECRET=xxx
9+
DATABASE_PASSWORD=xxx
10+
```
11+
12+
这些秘钥的值需要大家在哦本地都保持一样,秘钥最新值请参考:https://pox1djiawm.feishu.cn/docs/doccnroSzyajOrxn86MNw94VYke

backend/package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"main": "/bin/www.js",
88
"scripts": {
99
"serve": "cross-env NODE_ENV=production nodemon ./build/bin/www.js",
10-
"dev": "cross-env NODE_ENV=development nodemon ./build/bin/www.js",
10+
"dev": "cross-env NODE_ENV=development nodemon --inspect ./build/bin/www.js",
1111
"build": "ttsc",
1212
"build:watch": "ttsc -w"
1313
},
@@ -29,11 +29,13 @@
2929
"jsonwebtoken": "^8.5.1",
3030
"moment": "^2.29.0",
3131
"mysql2": "^2.1.0",
32+
"dotenv": "^8.2.0",
3233
"sequelize": "^6.3.5"
3334
},
3435
"devDependencies": {
3536
"@types/express": "^4.17.11",
3637
"@types/express-jwt": "^6.0.0",
38+
"@types/jsonwebtoken": "^8.5.0",
3739
"@types/node": "^14.11.4",
3840
"@types/validator": "^13.1.0",
3941
"@zerollup/ts-transform-paths": "^1.7.18",

backend/src/app.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
11
import express from 'express'
2-
import expressJwt from 'express-jwt'
32

4-
import config from 'bd7.config'
53
import { UserRouter, TestRouter } from '@routes'
6-
import { Restful } from '@utils'
7-
const { cryptoConfig } = config
4+
import { errorHandler, checkJWT } from '@middleware'
85

96
const app = express()
107

118
app.use(express.json())
129
app.use(express.urlencoded({ extended: false }))
13-
app.use(
14-
expressJwt({
15-
secret: cryptoConfig.password,
16-
algorithms: ['HS256'],
17-
requestProperty: 'auth',
18-
}).unless({
19-
path: ['/login', '/signup', '/api/test'], // 指定路径不经过 Token 解析
20-
}),
21-
)
10+
11+
/**
12+
* JWT中间件
13+
*/
14+
app.use(checkJWT)
15+
16+
/**
17+
* 业务路由
18+
*/
2219
app.use('/api/test', TestRouter)
2320
app.use('/api/user', UserRouter)
2421

25-
// https://liu-xin.me/2017/10/07/%E8%AE%A9Express%E6%94%AF%E6%8C%81async-await/
26-
app.use(function (err, req, res, next) {
27-
console.error('Error caught:', err)
28-
res.status(err.status).json(new Restful(err.code, err?.inner?.message))
29-
})
22+
// 包底错误处理中间件
23+
app.use(errorHandler)
3024

3125
export default app

backend/src/bd7.config.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { BinaryToTextEncoding } from 'crypto'
22
import { Options } from 'sequelize/types'
3+
import dotenv from 'dotenv'
4+
dotenv.config()
35

46
const sequelizeOptions: Options = {
57
// 数据库类别
@@ -32,8 +34,6 @@ const devConfig = {
3234
host:
3335
// "https://api.hokori.online" ||
3436
'http://localhost/',
35-
// 完整URL为: nginx配置下的转发路径 `${location}`
36-
baseURL: '/bd7',
3737
cryptoConfig: {
3838
// 每次分段加密的字符串最大长度(优先度高于cryptCount字段)
3939
onceCryptLength: 5,
@@ -44,7 +44,7 @@ const devConfig = {
4444
// 可选值:['hex', 'Base64', ...]
4545
digest: 'hex' as BinaryToTextEncoding,
4646
// 用于cipher对称加密生成密钥的密码
47-
password: 'bd7',
47+
secret: process.env.ACCESS_TOKEN_SECRET as string,
4848
},
4949
dataBaseConfig: {
5050
// 数据库名
@@ -54,14 +54,16 @@ const devConfig = {
5454
user: 'bd7',
5555

5656
// 密码
57-
password: 'M4NshB5mLw5r5c83',
57+
password: process.env.DATABASE_PASSWORD as string,
5858

5959
// options
6060
options: sequelizeOptions,
6161

6262
// 时区
6363
timezone: '+08:00',
6464
},
65+
// 12个小时
66+
tokenExpiredTime: '12h',
6567
}
6668

6769
const prodConfig = {

backend/src/database/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ const { dataBaseConfig } = config
55

66
const { database, user, password, options } = dataBaseConfig
77

8-
const DB = new Sequelize(database, user, password, {
8+
const sequelize = new Sequelize(database, user, password, {
99
...options,
1010
logging: isDev ? console.log : false, // 是否输出数据库日志
1111
})
1212

1313
const init = async () => {
14-
await DB.sync({ alter: isDev })
14+
await sequelize.sync({ alter: isDev })
1515
console.log('All models were synchronized successfully.')
1616
}
1717
export { init }
18-
export default DB
18+
export default sequelize

backend/src/middleware/checkJWT.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import expressJwt from 'express-jwt'
2+
import config from 'bd7.config'
3+
import { ROUTER_WHITE_LIST } from '@utils'
4+
5+
const {
6+
cryptoConfig: { secret },
7+
} = config
8+
export default expressJwt({
9+
secret,
10+
algorithms: ['HS256'],
11+
requestProperty: 'auth',
12+
}).unless({
13+
path: ROUTER_WHITE_LIST, // 指定路径不经过 Token 解析
14+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { CodeDictionary, Restful } from '@utils'
2+
3+
const tokenCodeDictionary = {
4+
credentials_required: CodeDictionary.JWT_ERROR__REQUIRED,
5+
invalid_token: CodeDictionary.JWT_ERROR__EXPIRED,
6+
}
7+
export default (err, req, res, next) => {
8+
if (err.name !== 'UnauthorizedError') {
9+
console.error('Error caught:', err)
10+
} else {
11+
err.code = tokenCodeDictionary[err.code]
12+
}
13+
res.status(err.status).json(new Restful(err.code, err?.inner?.message))
14+
}

backend/src/middleware/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import errorHandler from './errorHandler'
2+
import checkJWT from './checkJWT'
3+
export { errorHandler, checkJWT }
4+
export default {
5+
errorHandler,
6+
checkJWT,
7+
}

backend/src/routes/TestRouter.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,21 @@ const ROUTER = EXPRESS.Router()
88
ROUTER.get('/', (_req, res, next) => {
99
res
1010
.status(200)
11-
.json(new Restful(0, 'Hello world', `Time now is ${currentTime}`))
11+
.json(
12+
new Restful(
13+
0,
14+
'Hello world(no need for token)',
15+
`Time now is ${currentTime}`,
16+
),
17+
)
18+
next()
19+
})
20+
ROUTER.get('/token', (_req, res, next) => {
21+
res
22+
.status(200)
23+
.json(
24+
new Restful(0, 'Hello world(token needed)', `Time now is ${currentTime}`),
25+
)
1226
next()
1327
})
1428
export default ROUTER

0 commit comments

Comments
 (0)