登入模块1
This commit is contained in:
父節點
61caf5458e
當前提交
fd03c2d08f
@ -14,11 +14,17 @@
|
|||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"@types/node": "^16.4.1",
|
"@types/node": "^16.4.1",
|
||||||
|
"@types/tough-cookie": "^4.0.1",
|
||||||
|
"axios": "^0.21.1",
|
||||||
|
"axios-cookiejar-support": "^1.0.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
"express-validator": "^6.12.1",
|
||||||
"promise-mysql": "^5.0.3",
|
"promise-mysql": "^5.0.3",
|
||||||
|
"qs": "^6.10.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"tough-cookie": "^4.0.0",
|
||||||
"ts-node": "^10.1.0",
|
"ts-node": "^10.1.0",
|
||||||
"typedi": "^0.10.0"
|
"typedi": "^0.10.0"
|
||||||
}
|
}
|
||||||
|
1029
src/helpers/des.js
Normal file
1029
src/helpers/des.js
Normal file
檔案差異因為檔案過大而無法顯示
載入差異
@ -0,0 +1,66 @@
|
|||||||
|
import express, {Request, Response} from "express"
|
||||||
|
import {validationResult} from "express-validator"
|
||||||
|
import {IResultJson} from "./types"
|
||||||
|
import axios from "axios"
|
||||||
|
import axiosCookieJarSupport from "axios-cookiejar-support"
|
||||||
|
import tough from 'tough-cookie'
|
||||||
|
import mysql, {Pool} from 'promise-mysql'
|
||||||
|
import {appConfig} from "./config"
|
||||||
|
|
||||||
|
let db: Pool
|
||||||
|
let poolCreatingPromise = mysql.createPool({
|
||||||
|
host: appConfig.dbHost,
|
||||||
|
user: appConfig.dbName,
|
||||||
|
password: appConfig.dbPassword,
|
||||||
|
database: appConfig.dbName
|
||||||
|
}).then(value => {
|
||||||
|
db = value
|
||||||
|
console.log('Pool created.')
|
||||||
|
}).error(error => {
|
||||||
|
console.error(error)
|
||||||
|
console.error('无法连线到资料库')
|
||||||
|
process.exit(-1)
|
||||||
|
})
|
||||||
|
|
||||||
|
export function getPoolCreatingPromise() {
|
||||||
|
return poolCreatingPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resultJson = {
|
||||||
|
success(data: any) {
|
||||||
|
return <IResultJson>{
|
||||||
|
status: true,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error(data: any) {
|
||||||
|
return <IResultJson>{
|
||||||
|
status: false,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasValidationErrors(req: express.Request, res: express.Response) {
|
||||||
|
let errors = validationResult(req)
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
res.json(resultJson.error(errors.array()))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAxiosInstance() {
|
||||||
|
let instance = axios.create({
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'
|
||||||
|
},
|
||||||
|
validateStatus: status => true,
|
||||||
|
withCredentials: true
|
||||||
|
})
|
||||||
|
axiosCookieJarSupport(instance)
|
||||||
|
instance.defaults.jar = new tough.CookieJar()
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
export {db}
|
10
src/index.ts
10
src/index.ts
@ -3,12 +3,18 @@ import express from 'express'
|
|||||||
import cors from 'cors'
|
import cors from 'cors'
|
||||||
import {appConfig} from "./config"
|
import {appConfig} from "./config"
|
||||||
import {userRouter} from "./routers/user-router"
|
import {userRouter} from "./routers/user-router"
|
||||||
|
import {getPoolCreatingPromise} from "./includes"
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
app.use(cors())
|
app.use(cors())
|
||||||
|
app.use(express.urlencoded({extended: true}))
|
||||||
|
app.use('/user', userRouter)
|
||||||
|
|
||||||
app.use(userRouter)
|
async function entrypoint(){
|
||||||
|
await getPoolCreatingPromise()
|
||||||
app.listen(appConfig.port, () => {
|
app.listen(appConfig.port, () => {
|
||||||
console.log('Server started at port ' + appConfig.port)
|
console.log('Server started at port ' + appConfig.port)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
entrypoint()
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
|
import 'reflect-metadata'
|
||||||
import {Service} from "typedi"
|
import {Service} from "typedi"
|
||||||
|
import {IUser} from "../types"
|
||||||
|
import {db} from "../includes"
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
class UserModel{
|
export class UserModel{
|
||||||
|
async insertUser(user:IUser){
|
||||||
|
await db.query('insert into users (username,realName,role) values(?,?,?) ' +
|
||||||
|
'ON DUPLICATE KEY UPDATE username=username',[
|
||||||
|
user.username,user.realName,user.role
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
|
import 'reflect-metadata'
|
||||||
import express from "express"
|
import express from "express"
|
||||||
|
import {Container} from "typedi"
|
||||||
|
import {UserService} from "../services/user-service"
|
||||||
|
import {body, validationResult,} from "express-validator"
|
||||||
|
import {hasValidationErrors} from "../includes"
|
||||||
|
|
||||||
|
let userService = Container.get(UserService)
|
||||||
|
|
||||||
let userRouter = express.Router()
|
let userRouter = express.Router()
|
||||||
|
userRouter.post('/login',
|
||||||
|
body('username').notEmpty().withMessage('请输入使用者名称'),
|
||||||
|
body('password').notEmpty().withMessage('请输入密码'),
|
||||||
|
async (req:express.Request, res:express.Response) => {
|
||||||
|
if(hasValidationErrors(req,res)) return
|
||||||
|
res.json(await userService.login(req.body.username,req.body.password))
|
||||||
|
})
|
||||||
|
|
||||||
export {userRouter}
|
export {userRouter}
|
||||||
|
46
src/services/user-service.ts
Normal file
46
src/services/user-service.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import 'reflect-metadata'
|
||||||
|
import {Inject, Service} from "typedi"
|
||||||
|
import {UserModel} from "../models/user-model"
|
||||||
|
import {getAxiosInstance, resultJson} from "../includes"
|
||||||
|
import {strEnc} from "../helpers/des"
|
||||||
|
import qs from 'qs'
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class UserService {
|
||||||
|
@Inject()
|
||||||
|
userModel!: UserModel
|
||||||
|
|
||||||
|
async login(username: string, password: string) {
|
||||||
|
let casUrl = 'https://pass.sdu.edu.cn/cas/login?service=https%3A%2F%2Fservice.sdu.edu.cn%2Ftp_up%2F'
|
||||||
|
let axios = getAxiosInstance()
|
||||||
|
let resp = await axios.get(casUrl)
|
||||||
|
if (resp.status != 200) {
|
||||||
|
return resultJson.error('无法连线至认证伺服器')
|
||||||
|
}
|
||||||
|
let ticket = /name="lt" value="(.*?)"/.exec(resp.data)?.[1] || null
|
||||||
|
if (!ticket) {
|
||||||
|
return resultJson.error('无法取得ticket')
|
||||||
|
}
|
||||||
|
let rsa = strEnc(username + password + ticket, '1', '2', '3')
|
||||||
|
resp = await axios.post(casUrl, qs.stringify({
|
||||||
|
rsa,
|
||||||
|
ul: username.length.toString(),
|
||||||
|
pl: password.length.toString(),
|
||||||
|
execution: 'e1s1',
|
||||||
|
_eventId: 'submit'
|
||||||
|
}))
|
||||||
|
if (resp.status != 200) {
|
||||||
|
return resultJson.error('无法连线至认证伺服器')
|
||||||
|
}
|
||||||
|
if (!resp.data.includes('退出登录')) {
|
||||||
|
return resultJson.error('使用者名称或密码有误,请重新输入')
|
||||||
|
}
|
||||||
|
let realName = / <\/p> <span class="tit">(.*?)</.exec(resp.data)?.[1]!
|
||||||
|
await this.userModel.insertUser({
|
||||||
|
username,
|
||||||
|
realName,
|
||||||
|
role: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
11
src/types.ts
Normal file
11
src/types.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface IResultJson {
|
||||||
|
status: boolean,
|
||||||
|
data: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUser {
|
||||||
|
id?: number,
|
||||||
|
username: string,
|
||||||
|
realName: string,
|
||||||
|
role: 1 | 2
|
||||||
|
}
|
載入中…
x
新增問題並參考
Block a user