التوثيق
التوثيق يتم باستخدام معالج البرمجيات المتوسطة @Security('name', ['scopes']) مصمم في جهاز التحكم اسم المخطط محدد للمستخدمين: jwt.. api_key.. sessionأو tsoa_auth كل شيء صالح طالما تستخدم نفس الاسم spec.securityDefinitions.. @Security(...)و وحدة التوثيق الخاصة بك. المرجع ذو الصلة بالطلب: @Security.. @NoSecurity.. @Request.. @Res.. @Responseو TsoaResponse.
أولا، تعريف التعاريف الأمنية OpenAPIو أيضاً تُخيّل مكان مُعالجة المُتوثّقات في هذه الحالة authentication.ts ملف
{
"spec": {
"securityDefinitions": {
"api_key": {
"type": "apiKey",
"name": "access_token",
"in": "query"
},
"jwt": {
"type": "oauth2",
"authorizationUrl": "http://swagger.io/api/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify things",
"read:pets": "read things"
}
}
},
...
},
"routes": {
"authenticationModule": "./authentication.ts",
...
}
}في الإطار الأوسط، تصدير الوظيفة التي تستند إليها المكتبة (Express.. Koa.. Hapiأنت تستخدم. أنت فقط تخلق وظيفة واحدة في كل مرة وتتعامل مع أنواع الأمن داخله. The securityName و scopes تأتي من الشروح التي وضعتها فوق وظيفة مراقبك
- The
securityDefinitionsالمفتاحsecurityNameيجب أن تتأكد من وحدة التوثيق الخاصة بك يجب أن تتطابق تماماًtsoa-nextلا يحتفظ بأي اسم معين أو في حالة خاصة.
./authentication.ts
import * as express from "express";
import * as jwt from "jsonwebtoken";
export function expressAuthentication(
request: express.Request,
securityName: string,
scopes?: string[]
): Promise<any> {
if (securityName === "api_key") {
let token;
if (request.query && request.query.access_token) {
token = request.query.access_token;
}
if (token === "abc123456") {
return Promise.resolve({
id: 1,
name: "Ironman",
});
} else {
return Promise.reject({});
}
}
if (securityName === "jwt") {
const token =
request.body.token ||
request.query.token ||
request.headers["x-access-token"];
return new Promise((resolve, reject) => {
if (!token) {
reject(new Error("No token provided"));
}
jwt.verify(token, "[secret]", function (err: any, decoded: any) {
if (err) {
reject(err);
} else {
// Check if JWT contains all required scopes
for (const scope of scopes ?? []) {
if (!decoded.scopes.includes(scope)) {
reject(new Error("JWT does not contain required scope."));
}
}
resolve(decoded);
}
});
});
}
}
import * as hapi from "@hapi/hapi";
export function hapiAuthentication(
request: hapi.Request,
securityName: string,
scopes?: string[]
): Promise<any> {
// See above
}
import { Request } from "koa";
export function koaAuthentication(
request: Request,
securityName: string,
scopes?: string[]
): Promise<any> {
// See above
}./controllers/securityController.ts
import { Get, Request, Res, Response, Route, Security, TsoaResponse } from "tsoa-next";
@Route("secure")
export class SecureController {
@Response<{ message: string }>("default", "Unexpected error")
@Security("api_key")
@Get("UserInfo")
public async userInfo(@Request() request: { user: { id: number; name: string } }): Promise<{ id: number; name: string }> {
return Promise.resolve(request.user);
}
@Response<{ message: string }>("default", "Unexpected error")
@Security("jwt", ["admin"])
@Get("EditUser")
public async editUser(
@Request() request: { user?: { id: number; name: string } },
@Res() notFoundResponse: TsoaResponse<404, { message: string }>
): Promise<{ id: number; name: string }> {
if (!request.user) {
return notFoundResponse(404, { message: "Not found" });
}
return request.user;
}
}الأمن على نطاق المنظمة
إذا تشاطرتِ أغلبيّتكِ نفس المطلب يمكنكِ تطبيقه مرة على مستوى العينة spec.rootSecurity وبعد ذلك تجاوزه على فرادى المتحكمين أو الإجراءات @Security(...) أو @NoSecurity().
{
"spec": {
"rootSecurity": [{ "api_key": [] }]
}
}