0. Preface
Disclaimer: This article is for technical research and classroom automation testing demonstration only. It does not encourage or support any behavior that violates the platform service agreement or infringes upon the rights of teachers and schools. Do not use the script in this article on real production accounts or in formal teaching scenarios; otherwise, you are solely responsible for all consequences.
I. Analysis of learnCourseViewModel.js
The main saving logic of this module:
- Section Record Saving: Every time a section is finished, the learning record of the section is saved, including the completion status and answering status of all subordinate pages.
- Page-level Learning Status Collection: The record of each page (such as watching videos, doing exercises, voice input) is maintained by the page component itself, but ultimately uploaded and saved centrally in the section-level data.
- Timed Save + Save on Leave + Save on Page Switch: Ensures progress is retained to the maximum extent in cases of accidental exit, network disconnection, jumping, etc.
- Support for Third-party Platform Synchronization Saving: Provides callbacks for LMS or other learning platforms.
1.1 Core function for saving learning records
section.createRecord(force, status, chapterId, successCallback, failCallback, isLeave)
Parameter Meaning:
| Parameter | Meaning |
|---|---|
force | Whether to force save (true means force submit even if there are no changes) |
status | Whether completed (0 incomplete, 1 completed) |
chapterId | Chapter ID (used for aggregated upload) |
successCallback | Callback function after successful save |
failCallback | Callback function after failed save |
isLeave | Whether it is called when leaving the page (controls whether to prompt) |
Usage Example:
The meaning of this line of code is: Save the learning record of the current section, mark it as incomplete, and trigger record upload.
1.2 Timing of Triggering Save (Very Critical)
1. Automatic Timed Save (Every 5 minutes)
2. Save When Leaving the Page
3. Save When Switching Pages
In the selectPage function, if switching sections, save the current section record first before jumping:
4. Save When Returning to Directory or Exiting Learning
5. User Manually Clicks Save Button
1.3 Automatic Save Logic Upon Section Completion
There is a very clever interval listener:
This indicates: The system scans all pages under the current section every 5 seconds. Once it finds that all are finished, it automatically saves the record as "completed status".
1.4 Synchronization Mechanism with Third-Party Platforms
1. URL Parameter Control
Supports the following parameters to trigger synchronization save:
jtoken: Used to identify the third-party identity tokentrdCourseId,classId,callbackUrl
2. Call Synchronization Interface
1.5 Save Failure Recovery Mechanism
The system records failed section records to localStorage.failureRecord:
1.6 Fault Tolerance Mechanism and Status Judgment
The following judgments are used extensively before and after saving to prevent repeated or erroneous triggers:
isPreviewMode,isExpiredMode→ Whether it is preview mode or expired mode (skip save)section.isRecordLoaded()→ Whether the section's learning record has been loadedpage.hasStarted,page.questionIncomplete→ Determine if questions or voice tasks are completed
1.7 Analysis of Save Request Origin
Key Call:
This is the unified entry point for saving learning records, and the Section object is loaded from:
This means its .createRecord() method is the core method for sending save requests.
Request Header Information
All AJAX requests are uniformly configured in $.ajaxSetup:
Save URL Path
From the third-party synchronization interface path, it can be seen that the API host is configured as:
And the own learning record save interface might be:
Or similar:
These paths may be defined in the
model/Section.jsmodule.
II. Analysis of Section.js
According to the Section.js file, the data submitted to the backend during "save learning record" is encrypted via CryptoJS and then sent via an AJAX POST request. The interface path is:
2.1 Request Data Structure
This is the ItemStudyRecordUpdateDTO data object ultimately submitted:
⚠️ This structure is processed with DES encryption before the request:
CodeBlock Loading...
2.2 Brief Analysis of Construction Process
Page Loop Construction
pageStudyRecordDTOList:CodeBlock Loading...Extract Question Records Within Each Page:
CodeBlock Loading...Video Record Detailed Structure:
CodeBlock Loading...Speaking Task Record Structure:
CodeBlock Loading...
2.3 Failure Handling and Local Cache
When a request fails, the following is called:
The save structure is as follows:
2.4 Encryption and Decryption
There is a very critical section in Section.js:
Encryption Algorithm Parameters:
| Parameter | Value |
|---|---|
| Algorithm | DES (Symmetric Encryption) |
| Key | "12345678" (Fixed String) |
| Encoding | Utf8.parse(...) |
| Mode | ECB (Electronic Codebook Mode) |
| Padding | Pkcs7 (Common Padding Method) |
Encryption Result
The encrypted string generated by this method is Base64 encoded ciphertext. It is sent as the body of the POST request.
III. Key Points of Source Code Reverse Engineering
| Key Point | Details |
|---|---|
| Learning Record Structure | itemid、autoSave、complete、pageStudyRecordDTOList … |
| Encryption Implementation | CryptoJS.DES.encrypt(JSON, key="12345678", ECB, Pkcs7) |
| Interface | POST /api/yws/api/personal/sync?courseType=4&platform=PC |
| Directory API | /api/course/stu/{courseId}/directory?classId=… |
| Chapter → WholePage | /api/wholepage/chapter/stu/{nodeId} |
| Question Answer API | /api/questionAnswer/{questionId}?parentId={parentId} |
→ The frontend integrates all page data and submits the section-level learning record at once. As long as the fields are correct, the backend writes to the database. → DES key is hardcoded, ECB mode ⇒ Encryption can be fully reproduced.
IV. Overall Script Flowchart
V. Analysis of Key Code Snippets
4.1 DES-ECB Encryption Function
Behaves 100% consistently with frontend CryptoJS.
4.2 Forge Single Page Learning Record
4.3 Assemble Section-Level DTO and Upload
VI. Highlights of Full Script Functionality
| Feature | Description |
|---|---|
| Multi-course interaction | Calls course list interface, supports user selection |
| Chapter-Section Smart Traversal | Automatically identifies Video pages / PPT pages / Quiz-only pages |
| 100% Quiz Accuracy | Question answer interface returns correctAnswerList, script assembles based on question type |
| Reasonable Timestamp | studyStartTime, startEndTimeList consistent with server time zone |
| Friendly Logging | Prints itemid + pageid + section title on upload success/failure |
| Exception Fallback | If interface returns 4xx/5xx, displays res.text for easy troubleshooting |
Full Code
VII. Risks and Pitfalls
- Backend Risk Control
- Long-term high-frequency batch submission is easy to trigger
429 Too Many Requests; the script hastime.sleep(1)throttling.
- Long-term high-frequency batch submission is easy to trigger
- Question Bank Changes
- If the questions are set to "random selection", the old questionid will be invalid → the script just needs to fetch the real-time id.
- Hardcoded Keys
- If the official updates the key or changes to AES/CBC, the script needs to be adjusted synchronously.
- Account Ban Risk
- Massive completion in seconds + 100 points is extremely easy to be marked by the backend. Be sure to use it only in test classes or teaching aid whitelist environments.
VIII. One-Click Run Guide
Runtime interaction flow:
- Copy browser
token→ Paste into script - Select course number
- Sit back and harvest, observe logs
IX. Example Results
All sections uploaded in < 2 minutes, backend learning report shows Completed / 100 Points.
X. Conclusion
Through reading the frontend source code, we found that weak symmetric encryption + frontend hardcoded keys are common in low-cost LMS platforms. This provides convenience for testers but also exposes the platform's interface security shortcomings.
The Right Way:
- The backend should perform effective duration verification / video playback interval comparison for each record.
- Adopt dynamic key negotiation or JWT + HMAC signature verification.
- The server should save original playback logs for secondary risk control.
I hope the ideas in this article can help QA, teaching assistants, or course developers to automatically verify course links faster, and also provide some reference for improvement to the platform security team.