当前位置:网站首页>3、 Midway interface security certification
3、 Midway interface security certification
2022-07-24 08:31:00 【Code road hero】
Before reading this article , You need to read the pre content in advance :
One 、Midway Additions and deletions
Two 、Midway Add, delete, modify and check the packaging and tool classes
3、 ... and 、Midway Interface security authentication
Four 、Midway Integrate Swagger And support JWT bearer
5、 ... and 、Midway Use of environment variables in
A lot of times , The back-end interface can only be accessed after login , Even some interfaces need to have corresponding permissions to access .
Realize here bearer Verification mode (bearerFormat by JWT).
install JWT Components
>npm i @midwayjs/[email protected] --save
>npm i @types/jsonwebtoken --save-dev
After the installation package.json The following configurations will appear in the file
{
"dependencies": {
"@midwayjs/jwt": "^3.3.11"
},
"devDependencies": {
"@types/jsonwebtoken": "^8.5.8"
}
}
add to JWT To configure
- modify
src/config/config.default.ts, Add the following ;
// src/config/config.default.ts
jwt: {
secret: 'setscrew',
expiresIn: 60 * 60 * 24,
}
- register
JWTComponents ;
// src/configuration.ts
import * as jwt from '@midwayjs/jwt';
@Configuration({
imports: [
jwt,
//...
],
})
export class ContainerLifeCycle {
//...
}
About JWT Detailed use documents of , see :http://www.midwayjs.org/docs/extensions/jwt
install Redis Components
>npm i @midwayjs/[email protected] --save
>npm i @types/ioredis --save-dev
After the installation package.json The following configurations will appear in the file
{
"dependencies": {
"@midwayjs/redis": "^3.0.0"
},
"devDependencies": {
"@types/ioredis": "^4.28.7"
}
}
register Redis Components
// src/configuration.ts
import * as redis from '@midwayjs/redis';
@Configuration({
imports: [
redis,
// ...
],
})
export class ContainerLifeCycle {
// ...
}
Add the configuration
modify src/config/config.default.ts, Add the following :
add to Redis To configure
// src/config/config.default.ts
redis: {
client: {
host: 127.0.0.1,
port: 6379,
db: 0,
},
}
About Redis Detailed use documents of , see :http://www.midwayjs.org/docs/extensions/redis
Add security interception configuration
// src/config/config.default.ts
app: {
security: {
prefix: '/api', # Specified /api The initial interface address needs to be intercepted
ignore: ['/api/login'], # Specify the interface address , No interception required
},
}
Add interface security interception middleware
Add constant definition
// src/common/Constant.ts
export class Constant {
// When logging in to verify , Cache user login status KEY The prefix of
static TOKEM = 'TOKEN';
}
Add user access context class
// src/common/UserContext.ts
/** * Store the status data of the access context after login , There will also be redis In cache */
export class UserContext {
userId: number;
username: string;
phoneNum: string;
constructor(userId: number, username: string, phoneNum: string) {
this.userId = userId;
this.username = username;
this.phoneNum = phoneNum;
}
}
Add or edit src/interface.ts, take UserContext Sign up to ApplecationContext in
// src/interface.ts
import '@midwayjs/core';
import {
UserContext } from './common/UserContext';
declare module '@midwayjs/core' {
interface Context {
userContext: UserContext;
}
}
New Middleware src/middleware/security.middleware.ts
// src/middleware/security.middleware.ts
import {
Config, Inject, Middleware } from '@midwayjs/decorator';
import {
Context, NextFunction } from '@midwayjs/koa';
import {
httpError } from '@midwayjs/core';
import {
JwtService } from '@midwayjs/jwt';
import {
UserContext } from '../common/UserContext';
import {
RedisService } from '@midwayjs/redis';
import {
Constant } from '../common/Constant';
/** * Security verification */
@Middleware()
export class SecurityMiddleware {
@Inject()
jwtUtil: JwtService;
@Inject()
cacheUtil: RedisService;
@Config('app.security')
securityConfig;
resolve() {
return async (ctx: Context, next: NextFunction) => {
if (!ctx.headers['authorization']) {
throw new httpError.UnauthorizedError(' Lack of credentials ');
}
const parts = ctx.get('authorization').trim().split(' ');
if (parts.length !== 2) {
throw new httpError.UnauthorizedError(' Invalid credentials ');
}
const [scheme, token] = parts;
if (!/^Bearer$/i.test(scheme)) {
throw new httpError.UnauthorizedError(' The lack of Bearer');
}
// verification token, The expiration will throw an exception
const jwt = await this.jwtUtil.verify(token, {
complete: true });
// jwt Stored in the user Information
const payload = jwt['payload'];
const key = Constant.TOKEM + ':' + payload.userId + ':' + token;
const ucStr = await this.cacheUtil.get(key);
// Stored in the server-side cache user Information
const uc: UserContext = JSON.parse(ucStr);
if (payload.username !== uc.username) {
throw new httpError.UnauthorizedError(' Invalid credentials ');
}
// Stored in the access context
ctx.userContext = uc;
return next();
};
}
public match(ctx: Context): boolean {
const {
path } = ctx;
const {
prefix, ignore } = this.securityConfig;
const exist = ignore.find((item) => {
return item.match(path);
});
return path.indexOf(prefix) === 0 && !exist;
}
public static getName(): string {
return 'SECURITY';
}
}
@Config('app.security')Decoration , Specify load profilesrc/config/config.**.tsThe corresponding configuration information in ;- Use
JwtServiceConduct JWT Code check ;
jwt tokenEncode the user information in token in , After decoding, the corresponding user data can be obtained , Usually , No need to store in redis in ;
But one drawback is , You can't artificially control the distribution token invalid . therefore , Sometimes people use user information in the cache ;
It's used here JWT+Redis The way , To demonstrate two approaches ;
Register middleware
// src/configuration.ts
this.app.useMiddleware([SecurityMiddleware, FormatMiddleware, ReportMiddleware]);
Add login interface
- add to DTO;
// src/api/dto/CommonDTO.ts
export class LoginDTO {
username: string;
password: string;
}
- add to VO;
// src/api/vo/CommonVO.ts
export class LoginVO {
accessToken: string;
expiresIn: number;
}
- modify
src/service/user.service.ts, Add find user interface by user name ;
import {
Provide } from '@midwayjs/decorator';
import {
User } from '../eneity/user';
import {
InjectEntityModel } from '@midwayjs/orm';
import {
Repository } from 'typeorm';
import {
BaseService } from '../common/BaseService';
@Provide()
export class UserService extends BaseService<User> {
@InjectEntityModel(User)
model: Repository<User>;
getModel(): Repository<User> {
return this.model;
}
async findByUsername(username: string): Promise<User> {
return this.model.findOne({
where: {
username } });
}
}
- add to Controller
src/controller/common.controller.ts;
// src/controller/common.controller.ts
import {
Body, Config, Controller, Inject, Post } from '@midwayjs/decorator';
import {
Context } from '@midwayjs/koa';
import {
UserService } from '../service/user.service';
import {
RedisService } from '@midwayjs/redis';
import {
LoginDTO } from '../api/dto/CommonDTO';
import {
LoginVO } from '../api/vo/CommonVO';
import {
SnowflakeIdGenerate } from '../utils/Snowflake';
import {
JwtService } from '@midwayjs/jwt';
import {
Assert } from '../common/Assert';
import {
ErrorCode } from '../common/ErrorCode';
import {
UserContext } from '../common/UserContext';
import {
Constant } from '../common/Constant';
import {
ILogger } from '@midwayjs/core';
import {
decrypt } from '../utils/PasswordEncoder';
import {
Validate } from '@midwayjs/validate';
import {
ApiResponse, ApiTags } from '@midwayjs/swagger';
@ApiTags(['common'])
@Controller('/api')
export class CommonController {
@Inject()
logger: ILogger;
@Inject()
ctx: Context;
@Inject()
userService: UserService;
@Inject()
cacheUtil: RedisService;
@Inject()
jwtUtil: JwtService;
@Inject()
idGenerate: SnowflakeIdGenerate;
@Config('jwt')
jwtConfig;
@ApiResponse({
type: LoginVO })
@Validate()
@Post('/login', {
description: ' land ' })
async login(@Body() body: LoginDTO): Promise<LoginVO> {
const user = await this.userService.findByUsername(body.username);
Assert.notNull(user, ErrorCode.UN_ERROR, ' Wrong username or password ');
const flag = decrypt(body.password, user.password);
Assert.isTrue(flag, ErrorCode.UN_ERROR, ' Wrong username or password ');
const uc: UserContext = new UserContext(user.id, user.username, user.phoneNum);
const at = await this.jwtUtil.sign({
...uc });
const key = Constant.TOKEM + ':' + user.id + ':' + at;
const expiresIn = this.jwtConfig.expiresIn;
this.cacheUtil.set(key, JSON.stringify(uc), 'EX', expiresIn);
const vo = new LoginVO();
vo.accessToken = at;
vo.expiresIn = expiresIn;
return vo;
}
}
Use Postman verification
- Call interface ( Voucher is not set );

- Use the login interface to get token;

- Call interface ( Using credentials );

copyright , Reprint please indicate the source [ Code track success ]
边栏推荐
- P1739 expression bracket matching problem solution
- Hack the box - Introduction to networking module detailed Chinese tutorial
- "Problem solving" Batman's trouble
- Cmake binary installation
- Wechat applet file types and functions
- Uva572 oil deposits problem solution
- [multithreading] five communication modes between multithreads
- Detailed explanation of wechat applet page configuration and sitemap configuration parameters
- Clear up some disk space and try again
- [wechat applet development (native)] canvas animation
猜你喜欢

Wei Xiaoli's "pursuer" is coming

How difficult is it to build a digital collection platform?

"Solution" friend of Vulcan

Is gamefi in decline or in the future?

Figure storage geabase
![[wechat applet development] (II) wechat native bottom tabbar configuration](/img/74/5f5da7ea47f95a25011ba52959f480.png)
[wechat applet development] (II) wechat native bottom tabbar configuration

About the big hole of wechat applet promise
![[wechat applet development (III)] realize the stacking and sliding of cards](/img/6c/4ebd60a2106b56b8bf3a6bf17d11f9.png)
[wechat applet development (III)] realize the stacking and sliding of cards

Enterprises love hybrid app development, and applet container technology can improve efficiency by 100%

3587. Connected graph (Jilin University postgraduate entrance examination machine test question)
随机推荐
Using golang to implement RPC (1)
Cososcreator upgrade gradle version
Look at the most influential infrastructure m-dao of Web3 through the current situation of Dao
JQ native write bullet frame mask layer
Wechat applet file types and functions
Digital collections "chaos", 100 billion market changes are coming?
[interview] Why do you need foreach with the for cycle?
「题解」火神之友
Vscode code style notes (vetur)
Protocol buffer learning notes
In the next bull market, can platofarm, the leading project in the Web3 world, set foot on the top of the mountain
Wargames NATAS (11-15) problem solving essay
Web3≠NFT? A digital Renaissance?
MySQL counts the total sales data of each month
Go: how to gracefully time out
FPGA integrated project - image edge detection system
Hack the box - Introduction to networking module detailed Chinese tutorial
3587. Connected graph (Jilin University postgraduate entrance examination machine test question)
Golang implements sanggi diagram and analyzes user behavior trajectory
MySQL日期格式化