Administrators of Qoder CN Enterprise Dedicated Edition and organization-wide administrators can configure security filters for AI chat, code completion, and knowledge base uploads.
The new Qoder CN documentation site is now available. Content on this site may not reflect the latest product features and changes. Visit docs.qoder.cn for the latest product documentation.
This feature supports only Visual Studio Code and JetBrains IDE extensions. It is not available in the Qoder CN IDE.
|
Applicable editions |
Enterprise Dedicated Edition |
Access the feature
-
Log in to the Qoder CN console as a Qoder CN administrator or an organization-wide administrator (Enterprise Dedicated Edition only). In the left navigation pane, choose .
-
At the top of the page, select a tab based on the scenario where you want to apply the filter: AI Chat, Inline Code Generation, or Knowledge Base Upload (Enterprise Dedicated Edition only).
-
Enable the switch for each filter and configure its parameters. The following table lists the supported filter types:
Scenario
Filter type
Description
AI Chat
AI Chat pre-filter
When you use the AI Chat feature of Qoder CN, user input sent to the Large Language Model (LLM) passes through the pre-filter. LLM output passes through the post-filter.
AI Chat post-filter
Inline Code Generation
Inline Code Generation pre-filter
When you use the Inline Code Generation feature of Qoder CN, user input sent to the LLM passes through the pre-filter. LLM output passes through the post-filter.
Inline Code Generation post-filter
Knowledge Base Upload
Knowledge Base Upload pre-filter
Files uploaded to the Qoder CN knowledge base must pass this filter before upload succeeds.
Important-
Ensure developers upgrade their Qoder CN extension to version 1.4.0 or later. Otherwise, configured filters will not take effect.
-
After you enable or modify the AI Chat filter or Inline Code Generation filter, changes take about 5 to 10 minutes to take effect for developers using the Qoder CN extension.
-
After you enable or modify the Knowledge Base Upload filter, changes take effect immediately. Files uploaded to your enterprise knowledge base are filtered right away.
-
Configure pre-filters for AI Chat and Inline Code Generation
Method 1: Configure with regular expressions
Thoroughly test regular expressions before deployment to avoid performance issues in IDE extensions.
-
Processing method: Configure filters using regular expressions. Three modes are supported.
No action on match
Take no action when a match occurs.
Block on match
Block the request and stop the model call when a match occurs.
Replace on match
Replace content according to the configuration when a match occurs.
-
Notification: Enable notifications to send alerts to your preferred messaging platform using webhooks.
-
Execution order: Filters run in the order you configure them.
-
Maximum number of regular expressions: You can add up to 10 expressions.
-
Regular expression standard: Expressions follow the ECMAScript standard. Common flags such as
i(case-insensitive),g(global), ands(DOTALL) are supported. -
Example configurations:
Rule name
Regular expression
Replacement
Original text
Replaced text
ID number
(?<pre>.*)(\d{15})((\d{2})([0-9Xx]))(?<post>.*)
$<pre>***$<post>
ID number: 330204197709022312.
ID number: ***.
Email address
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
***
My email is lin***@aliyunmail.com
My email is ***
Password
(.*password=)([\w\d]+)(.*)
$1***$3
{password=1213213}
{password=***}
Method 2: Configure with custom scripts (Enterprise Dedicated Edition only)
The Enterprise Dedicated Edition supports custom script-based filtering for complex pre-filtering scenarios.
Step 1: Develop the script
Write scripts in TypeScript using the sample code as a reference.
-
Download the template repository: Click the repository URL: lingma-extension-template. This template includes scaffolding for script development. Read the
README.mdfile and code examples carefully. -
Implement the pre-processing interface: Implement the
RequestPreHandlerinterface. For API details, see Custom Script API. Here is an example implementation inSensitiveContentFilter.ts:/** * Sensitive content filter. Pre-processes data sent to the model. */ export const sensitiveContentFilter: RequestPreHandler = { handle: async (request: RawRequest, SDKTool: Qoder CNSDKTool) => { const dataMap = PayloadUtil.getPayloadData(request.payload); for (const [key, value] of dataMap.entries()) { if (value.includes('password')) { return ResultUtil.buildBlockResult('Content contains password'); } } // Handle different actions differently switch (request.action) { case ActionEnum.COMPLETION: // do something break; case ActionEnum.CODE_PROBLEM_SOLVE: // do something break; default: return ResultUtil.buildNoOpsResult(); } return ResultUtil.buildNoOpsResult(); }, }; -
Run and debug the script. Test it by running the
mainfunction. Follow these steps:Step 1
Edit the
src/index.tsfile. Modify themainfunction to test your script. Example:async function main() { const value1 = ['password=123', 'abc']; const value2 = 'hello world'; const dataMap = new Map<PayloadDataKeyEnum, PayloadDataValueType>(); dataMap.set(PayloadDataKeyEnum.SELECTED_CODE, value1); dataMap.set(PayloadDataKeyEnum.USER_INPUT, value2); const mockRequest: RawRequest = { action: ActionEnum.CODE_GENERATE_COMMENT, payload: { associatedContexts: [], data: dataMap, }, requestId: '123', }; const response = await sensitiveContentFilter.handle(mockRequest, SDKTool); console.log(response); }Step 2
In VS Code, open the script file and set breakpoints. Then, in the Debug view, select Launch Program and click Run.
The sample code file
index.tscontains the following content.import { sensitiveContentFilter } from './demo/SensitiveContentFilter'; import { ActionEnum, PayloadDataKeyEnum, PayloadDataValueType, RawRequest } from './sdk/RequestPreHxxx'; const SDKTool = { idePlatform: 'vscode', ideVersion: '1.0', pluginVersion: '1.0', user: { name: 'tester', organizationId: '123', organizationName: 'test_org', uid: 'org_123', }, };
Step 2: Compile and Build
Compile TypeScript to JavaScript. For example, compile SensitiveContentFilter.ts into SensitiveContentFilter.js:
-
Open the configuration file
src/build.js. Update theentryPointsandoutfileparameters. SetentryPointsto the path of your TypeScript file. Setoutfileto the output path for the compiled JavaScript file. -
Run the command
node build.jsfrom the root directory of your repository. After successful execution, the JavaScript file appears at the path specified inoutfile.
Step 3: Test locally
Test the script locally before uploading to verify it integrates with the Qoder CN IDE extension and filters correctly.
-
Copy the compiled JavaScript file to the
/extension/local/script/directory under the local storage path of Qoder CN. -
Edit the
config.jsonfile. This file is located in the/extension/local/directory under the local storage path of Qoder CN. Openconfig.jsonand findcontentHandlerScripts. Add your script's configuration. IfcontentHandlerScriptsdoes not exist, create a new array. Example:{ "contentHandlerScripts": [ { "identifier": "SensitiveContentFilter", "name": "Sensitive Content Filter", "version": "1.0.0", "scriptPath": "~/.lingma/extension/local/script/SensitiveContentFilter.js", "state": "enabled", "bizType": "completion" } ] }Parameter descriptions:
Parameter
Description
identifier
Script ID. Must be unique.
name
Script name.
version
Script version. Increment after each change, or the updated script will not take effect.
scriptPath
Script file path. Note:
-
The script must be placed in the
/extension/local/script/directory under the local storage path. -
The JavaScript file name (for example,
SensitiveContentFilter.js) must match theidentifiervalue.
state
Script state.
enabledenables the script.disableddisables it.bizType
Business scenario.
completionapplies to inline code generation.chatapplies to AI chat. -
Step 4: Upload the script
After local testing, upload the script:
-
Go to the Qoder CN console. Choose Policy Management. Select the scenario where you want to enable the security filter.
-
Select Custom Script as the filter option.
-
Upload the compiled JavaScript file.
-
Click Save Configuration. The configuration takes effect on the extension within about 5 minutes.
Custom Script API
Custom scripts support three processing methods:
-
Block: Stop further processing. No inference call is made to the LLM. The current request ends.
-
Filter: Modify the data sent (for example, obfuscate, delete, or replace content), then continue processing.
-
No operation: Return the data unchanged and continue processing.
Interface definition
/**
* Pre-processing interface for Qoder CN
*/
export interface RequestPreHandler {
// Process the request
handle: (request: RawRequest, SDKTool: Qoder CNSDKTool) => Promise<HandlerResponse>;
}
Input parameters
/**
* Request object. Includes the action and raw data sent to the LLM.
*/
export interface RawRequest {
// Unique identifier for the request. Used for tracing.
action: ActionEnum;
// Enum for the action that triggered the request.
payload: ContentPayload;
// Payload containing raw data.
requestId: string;
}
// Value type for ContentPayload.data
export type PayloadDataValueType = string | number | string[];
/**
* Payload containing raw data sent to the LLM.
*/
export class ContentPayload {
// Collection of data to process. Keys are defined in ContextValueKeyEnum.
data: Map<PayloadDataKeyEnum, PayloadDataValueType>;
// Context associated with the processing.
associatedContexts: ContextItem[];
constructor() {
this.data = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
this.associatedContexts = [];
}
}
/**
* Keys for ContentPayload.data
*/
export enum PayloadDataKeyEnum {
// Selected code snippet
SELECTED_CODE ='lingma:code',
// User input text
USER_INPUT = 'lingma:text',
// Error messages
ERROR_MESSAGES = 'lingma:error_messages',
// Terminal log output
TERMINAL_CONTENT = 'lingma:terminal_content',
// Code before cursor for code completion
PREFIX_CODE = 'lingma:code_prefix',
// Code after cursor for code completion
SUFFIX_CODE = 'lingma:code_suffix',
// Similar code snippets
SIMILAR_CODE = 'lingma:similar_code',
}
/**
* Enum for request actions
*/
export enum ActionEnum {
// Unit test
GENERATE_TESTCASE = 'GENERATE_TESTCASE',
// Generate comments
CODE_GENERATE_COMMENT = 'CODE_GENERATE_COMMENT',
// Explain code
EXPLAIN_CODE = 'EXPLAIN_CODE',
// Optimize code
OPTIMIZE_CODE = 'OPTIMIZE_CODE',
// Free input (direct text entry in the chat box)
FREE_INPUT = 'FREE_INPUT',
// Quick fix for code issues
CODE_PROBLEM_SOLVE = 'CODE_PROBLEM_SOLVE',
// Generate shell commands
TERMINAL_COMMAND_GENERATION = 'TERMINAL_COMMAND_GENERATION',
// Fix terminal errors
TERMINAL_EXPLAIN_FIX = 'TERMINAL_EXPLAIN_FIX',
// Code completion
COMPLETION = 'COMPLETION',
}
Output parameters
/**
* Pre-processing result
*/
export class HandlerResponse {
// Processing policy. Controls subsequent logic.
handlePolicy: HandlePolicy;
// Reason description
reason?: string;
// Required when handlePolicy=FILTER. Contains filtered data. Must match ContentRequest.payload structure.
payload?: ContentPayload;
constructor() {
// Default values
// eslint-disable-next-line @typescript-eslint/no-use-before-define
this.handlePolicy = HandlePolicy.NO_OPS;
this.reason = '';
this.payload = new ContentPayload();
}
}
/**
* Processing policy enum
*/
export enum HandlePolicy {
// Block the request
BLOCK = 'BLOCK',
// Filter the request and modify the payload
FILTER = 'FILTER',
// Take no action
NO_OPS = 'NO_OPS',
}
Configure post-filters for AI Chat and Inline Code Generation
Method 1: Configure with regular expressions
Thoroughly test regular expressions before deployment to avoid performance issues in IDE extensions.
-
Processing method: Configure filters using regular expressions. Only one mode is supported:
No action on match
Take no action when a match occurs.
-
Notification: Enable notifications to send alerts to your preferred messaging platform using webhooks.
-
Execution order: Filters run in the order you configure them.
-
Maximum number of regular expressions: You can add up to 10 expressions.
-
Regular expression standard: Expressions follow the ECMAScript standard. Common flags such as
i(case-insensitive),g(global), ands(DOTALL) are supported. -
Example configurations:
Rule name
Regular expression
Original text
ID number
(?<pre>.*)(\d{15})((\d{2})([0-9Xx]))(?<post>.*)
ID number: 330204197709022312.
Email address
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
My email is lin***@aliyunmail.com
Password
(.*password=)([\w\d]+)(.*)
{password=1213213}
Method 2: Configure with custom scripts (Enterprise Dedicated Edition only)
The Enterprise Dedicated Edition supports custom script-based filtering for complex post-filtering scenarios.
Step 1: Develop the script
Write scripts in TypeScript using the sample code as a reference.
-
Download the template repository: Click the repository URL: lingma-extension-template. This template includes scaffolding for script development. Read the
README.mdfile and code examples carefully. -
Implement the post-processing interface: Implement the
RequestPostHandlerinterface. For the API, refer to Custom Script API. The following is an implementation example from the code snippetLLMChatAuditHandler.ts, which audits AIChat operations of Qoder CN and reports the audit content to Alibaba Cloud SLS.import {ResultUtil} from '../common/HandlerRespUtil'; import { JsonUtil } from '../common/JsonUtil'; import {PayloadUtil} from '../common/PayloadUtil'; import {Config} from '../sdk/ConfigManager'; import {Qoder CNSDKTool} from '../sdk/Qoder CNSDKTool'; import axios from "axios"; import moment from "moment"; import os from "os"; import { ActionEnum, AIResponse, HandlePolicy, RawRequest, RequestPostHandler, RequestPreHandler } from '../sdk/RequestHandleSDK'; /** * Custom post-filter script. Sends request content to a remote server for processing (such as code scanning or content auditing). */ export const llmResultAuditHandler: RequestPostHandler = { handle: async (request: RawRequest, response: AIResponse,SDKTool: Qoder CNSDKTool) => { // Operator name let userName = SDKTool.user.name; // Operator ID let userId = SDKTool.user.uid; // IDE let ide = SDKTool.idePlatform; // IDE version let ideVersion = SDKTool.ideVersion; // Operation time let operationTime = moment().format("YYYY-MM-DD HH:mm:ss"); // Operation IP let opeartionIp = getIpAddress(); // Business scenario (completion or chat) let bizType = "chat"; // Request ID let requestId = request.requestId; // Action let action = request.action; // Operation content (select fields based on your audit needs. Avoid large payloads over 16 KB.) let inferredResult = response.inferredResult.text; // Report to SLS // SLS project name let slsProject = "xxx"; // SLS LogStore name let slsLogStore = "xxx"; // SLS endpoint let endPoint = "cn-hangzhou.log.aliyuncs.com"; let slsWebTrackingUrl = `http://${slsProject}.${endPoint}/logstores/${slsLogStore}/track?APIVersion=0.6.0&request_id=${requestId}&action=${action}&biz_type=${bizType}&user_name=${userName}&user_id=${userId}&ide=${ide}&ide_version=${ideVersion}&operation_time=${operationTime}&opeartion_ip=${opeartionIp}&inferredResult=${inferredResult}`; axios.get(slsWebTrackingUrl).catch((error) => { console.error(error); }); // Return filter result return ResultUtil.buildPostHandlerResponse(HandlePolicy.NO_OPS, response.inferredResult,'No action required'); }, }; /** * Add the custom script filter to the configuration * @param config Config object provided by Qoder CNExtensionSDK */ export function modifyConfig(config: Config) { config.postContentHandlers.push(llmResultAuditHandler); return config; } function getIpAddress() { const interfaces = os.networkInterfaces(); for (let devName in interfaces) { let iface = interfaces[devName]; for (let i = 0; i < iface.length; i++) { let alias = iface[i]; if ( alias.family === "IPv4" && alias.address !== "127.0.0.1" && !alias.internal ) return alias.address; } } return "No IP address found"; } -
Run and debug the script. Test it by running the
mainfunction. Follow these steps:Step 1
Edit the
src/index.tsfile. Modify themainfunction to test your script. Example:async function main() { const value2 = 'hello world'; const dataMap = new Map<PayloadDataKeyEnum, PayloadDataValueType>(); dataMap.set(PayloadDataKeyEnum.USER_INPUT, value2); const request: RawRequest = { action: ActionEnum.CODE_GENERATE_COMMENT, payload: { associatedContexts: [], data: dataMap, }, requestId: 'test-request-id', }; const aiResponse: AIResponse = { inferredResult: { text: 'reply hello world', }, }; const response = await llmResultAuditHandler.handle(request, aiResponse, SDKTool); console.log(response); }Step 2
In VS Code, open the script file and set breakpoints. Then, in the Debug view, select Launch Program and click Run.
The sample code file
index.tscontains the following content.import { sensitiveContentFilter } from './demo/SensitiveContentFilter'; import { ActionEnum, PayloadDataKeyEnum, PayloadDataValueType, RawRequest } from './sdk/RequestPreHxxx'; const SDKTool = { idePlatform: 'vscode', ideVersion: '1.0', pluginVersion: '1.0', user: { name: 'tester', organizationId: '123', organizationName: 'test_org', uid: 'org_123', }, };
Step 2: Compile and Build
Compile TypeScript to JavaScript. For example, compile LLMChatAuditHandler.ts into LLMChatAuditHandler.js:
-
Open the configuration file
src/build.js. Update theentryPointsandoutfileparameters. SetentryPointsto the path of your TypeScript file. Setoutfileto the output path for the compiled JavaScript file. -
Run the command
node build.jsfrom the root directory of your repository. After successful execution, the JavaScript file appears at the path specified inoutfile.
Step 3: Test locally
Test the script locally before uploading to verify it integrates with the Qoder CN IDE extension and filters correctly.
-
Copy the compiled JavaScript file to the
/extension/local/script/directory under the local storage path of Qoder CN. -
Edit the
config.jsonfile. This file is located in the/extension/local/directory under the local storage path of Qoder CN. Openconfig.jsonand findcontentHandlerScripts. Add your script's configuration. IfcontentHandlerScriptsdoes not exist, create a new array. Example:{ "contentHandlerScripts": [ { "identifier": "LLMChatAuditHandler", "name": "AI Chat Audit", "version": "1.0.0", "scriptPath": "~/.lingma/extension/local/script/LLMChatAuditHandler.js", "state": "enabled", "stage":"post", "bizType": "completion" } ] }Parameter descriptions:
Parameter
Description
identifier
Script ID. Must be unique.
name
Script name.
version
Script version. Increment after each change, or the updated script will not take effect.
scriptPath
Script file path. Note:
-
The script must be placed in the
/extension/local/script/directory under the local storage path. -
The JavaScript file name (for example,
LLMChatAuditHandler.js) must match theidentifiervalue.
state
Script state.
enabledenables the script.disableddisables it.stage
Processing stage.
postmeans post-filter.premeans pre-filter. Default ispre.bizType
Business scenario.
completionapplies to inline code generation.chatapplies to AI chat. -
Step 4: Upload the script
After local testing, upload the script:
-
Go to the Qoder CN console. Choose Policy Management. Select the scenario where you want to enable the security filter.
-
Select Custom Script as the filter option.
-
Upload the compiled JavaScript file.
-
Click Save Configuration. The configuration takes effect on the extension within about 5 minutes.
Custom Script API
Custom scripts support only one processing method:
-
No operation: Return the data unchanged and continue processing.
Interface definition
/**
* Post-processing interface for Qoder CN
* @param request User request
* @param response Inference result from the LLM
* @param SDKTool SDK utility class. Provides IDE and plugin information.
* @returns Result after post-processing
*/
export interface RequestPostHandler {
// Post-processing method
handle: (request: RawRequest, response: AIResponse, SDKTool: Qoder CNSDKTool) => Promise<PostHandlerResponse>;
}
Input parameters
/**
* Request object. Includes the action and raw data sent to the LLM.
*/
export interface RawRequest {
// Unique identifier for the request. Used for tracing.
action: ActionEnum;
// Enum for the action that triggered the request.
payload: ContentPayload;
// Payload containing raw data.
requestId: string;
}
/**
* Inference result from the model
*/
export class InferredResult {
// Text generated by the LLM
text: string;
constructor() {
this.text = '';
}
}
// Value type for ContentPayload.data
export type PayloadDataValueType = string | number | string[];
/**
* Payload containing raw data sent to the LLM.
*/
export class ContentPayload {
// Collection of data to process. Keys are defined in ContextValueKeyEnum.
data: Map<PayloadDataKeyEnum, PayloadDataValueType>;
// Context associated with the processing.
associatedContexts: ContextItem[];
constructor() {
this.data = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
this.associatedContexts = [];
}
}
/**
* Keys for ContentPayload.data
*/
export enum PayloadDataKeyEnum {
// Selected code snippet
SELECTED_CODE ='lingma:code',
// User input text
USER_INPUT = 'lingma:text',
// Error messages
ERROR_MESSAGES = 'lingma:error_messages',
// Terminal log output
TERMINAL_CONTENT = 'lingma:terminal_content',
// Code before cursor for code completion
PREFIX_CODE = 'lingma:code_prefix',
// Code after cursor for code completion
SUFFIX_CODE = 'lingma:code_suffix',
// Similar code snippets
SIMILAR_CODE = 'lingma:similar_code',
// File path for code completion
FILE_PATH = 'lingma:file_path',
}
/**
* Enum for request actions
*/
export enum ActionEnum {
// Unit test
GENERATE_TESTCASE = 'GENERATE_TESTCASE',
// Generate comments
CODE_GENERATE_COMMENT = 'CODE_GENERATE_COMMENT',
// Explain code
EXPLAIN_CODE = 'EXPLAIN_CODE',
// Optimize code
OPTIMIZE_CODE = 'OPTIMIZE_CODE',
// Free input (direct text entry in the chat box)
FREE_INPUT = 'FREE_INPUT',
// Quick fix for code issues
CODE_PROBLEM_SOLVE = 'CODE_PROBLEM_SOLVE',
// Generate shell commands
TERMINAL_COMMAND_GENERATION = 'TERMINAL_COMMAND_GENERATION',
// Fix terminal errors
TERMINAL_EXPLAIN_FIX = 'TERMINAL_EXPLAIN_FIX',
// Code completion
COMPLETION = 'COMPLETION',
}
Output parameters
/**
* Post-processing result
*/
export class PostHandlerResponse {
// Processing policy. Controls subsequent logic.
handlePolicy: HandlePolicy;
// Reason description
reason?: string;
// Processed inference result
processedResult: InferredResult;
constructor() {
// Default values
this.handlePolicy = HandlePolicy.NO_OPS;
this.reason = '';
this.processedResult = new InferredResult();
}
}
/**
* Encapsulates the LLM response
*/
export class AIResponse {
// Inference result
inferredResult: InferredResult;
constructor() {
this.inferredResult = new InferredResult();
}
}
/**
* Inference result from the model
*/
export class InferredResult {
// Text generated by the LLM
text: string;
constructor() {
this.text = '';
}
}
/**
* Processing policy enum (post-filters support only NO_OPS)
*/
export enum HandlePolicy {
// Block the request
BLOCK = 'BLOCK',
// Filter the request and modify the payload
FILTER = 'FILTER',
// Take no action
NO_OPS = 'NO_OPS',
}
Configure Knowledge Base Upload Filters (Enterprise Dedicated Edition only)
In the Enterprise Dedicated Edition, Qoder CN administrators and global administrators can configure knowledge base upload filters. After configuration, knowledge base files are reviewed before upload.
Configuration steps
Step 1: Enable and edit the knowledge base filter
-
In the left navigation pane, click Policy Configuration. On the right, click the Knowledge Base Filter tab.
-
In the Knowledge Base Filter configuration page, turn on the Enable or disable knowledge base upload pre-filter switch to edit parameters.
URL
Required
Endpoint for your third-party scanning service. The service must accept POST requests.
Token field name
Required
Name of the header field used to store the token.
Secret key
Required
Secret key used to generate the access token. The token is placed in the specified header field to verify request legitimacy. See the Secure Token section.
Step 2: Test connectivity
-
After entering the correct information, click Test Connection. The test succeeds if the third-party filter returns an HTTP
2xxstatus code. -
If another status code is returned, the test fails. Check your entries and try again.
Step 3: Save the knowledge base filter
Click Save Configuration to save your filter settings. The filter takes effect immediately after saving.
Third-party scanning service API
Your enterprise must provide a third-party scanning service that accepts POST requests. Only scanned content can be uploaded. The service interface must meet these requirements:
Request headers
|
Parameter name |
Required |
Description |
Parameter examples |
|
X-Auth-Raw |
Yes |
Authentication parameter. The parameter name matches the Token field name configured in the filter. The value is the token generated from the secret key using the encryption algorithm. See the Secure Token section for details. |
6c3baa76c62550eab864e6f75c4bb |
|
Content-Type |
Yes |
Media type for the request and response. |
multipart/form-data |
-
Secure Token: A secure signature designed by Alibaba Cloud to prevent malicious attackers from hijacking your cloud service permissions. Generating a token requires a secret key, current timestamp, additional data, and an encryption algorithm.
-
Token generation: When Qoder CN calls the third-party scanning service, it includes the secure token in the request header for authentication. Compute the token using these parameters:
token = sha256Hex(method + url + timestamp + tokenSecret) + timestampHexmethod
POST method.
url
URL of the scanning service endpoint you entered in the knowledge base filter configuration.
timestamp
Current timestamp.
tokenSecret
Secret key you entered in the knowledge base filter configuration.
timestampHex
Timestamp converted to hexadecimal.
-
Token verification: Your third-party scanning service can use the following code to validate the token.
Important-
Timestamp: Ensure client and server clocks are synchronized to avoid token validation failures due to clock skew.
-
Key management: Safeguard the
tokenSecret. Do not share it with unauthorized users. -
Expiration: Adjust the token lifetime based on your business needs. The example sets it to 60 seconds but you can change it.
/* * Method parameters: * receivedHash: Received hash, which includes the timestamp. * tokenSecret: Secret key used to generate the hash. * url: Request URL. */ public boolean validateAuthRaw(String receivedHash, String tokenSecret, String url) { final String method = "POST"; // Extract timestamp from receivedHash String tsHex = receivedHash.substring(receivedHash.length() - 8); long tsSec = Long.parseLong(tsHex, 16); // Compare timestamps. Allow up to 60 seconds difference. long now = System.currentTimeMillis() / 1000L; if (Math.abs(now - tsSec) > 60) { return false; // Timestamp outside allowed range } // Build string to sign String plain = method + url + tsSec + tokenSecret; // Generate expected hash String expectedHash = org.apache.commons.codec.digest.DigestUtils.sha256Hex(plain); // Compare hashes return expectedHash.equals(receivedHash.substring(0, receivedHash.length() - 8)); } -
Request parameters
|
Parameter name |
Type |
Required |
Description |
Parameter Example |
|
metadata |
string |
Yes |
Business metadata. Content-Type: application/json |
{"user": "user0000001", "queryId": "cd2fd109-c4d4-489f-9b27-53752f7827d6"} |
|
file |
file |
Yes |
File to scan |
Request example:
Content-Type: multipart/form-data; boundary=${bound}
--${bound}
Content-Disposition: form-data; name="metadata"
Content-Type: application/json
{
"user":"user0000001",
"queryID":"cd2fd109-c4d4-489f-9b27-53752f7827d6"
}
--${bound}
Content-Disposition: form-data; name="file"; filename="test-file.pdf"
Content-Type: application/pdf
%binary-file-content-here%
Response structure
The interface must return HTTP status code 200 and the following response body format.
|
Parameter name |
Type |
Required |
Description |
Parameter Example |
|
forbidden |
boolean |
Yes |
Security check result. true means the check failed. |
false |
|
errorMsg |
string |
No |
Error message explaining why the check failed. |
"File contains malicious content. Modify and re-upload." |
|
queryId |
string |
No |
Request ID. Must match the queryId field in the request metadata. |
"cd2fd109-c4d4-489f-9b27-53752f7827d6" |
|
user |
string |
No |
User ID. Must match the user field in the request metadata. |
"user0001" |