preface
It happened that the Nuggets had a new sign-in activity. It happened that they couldn’t sleep after drinking coffee and didn’t have to go to work during the double holidays. So I wrote a plug-in to facilitate weekday sign-in (by the way of practicing hands).
Let’s look at the finished product first
In summary, the plug-in needs to achieve the following goals:
- Detects the current user login status
- Determine if the user has checked in today
- Send a check-in request
- Display information (user information, reward information)
Analysis of the request
User login credentials
[POST] / Passport/Web/User/Login: The Cookie set by the request response contains several key-value pairs. If you select a normal request for PostMan analysis, you can see that the Nugget uses the SESSIONID in the Cookie as the login credentials of the user
Check-in to the relevant interface
In the request of check-in function, there are 4 interfaces related to the function to be realized this time, respectively:
- Gets a summary of the number of days you signed in
[GET]/growth_api/v1/get_counts
- Get the current number of ores
[GET]/growth_api/v1/get_cur_point
- Determine if the user has checked in today
[GET]/growth_api/v1/get_today_status
- User sign in
[POST]/growth_api/v1/check_in
Here is a brief analysis of the function corresponding to the request, the specific parameters and the meaning of the return value can be viewed through the browser console (
F12
)
The flow chart
The following is a sequence diagram of several scenarios to illustrate the workflow of the plug-in
Unlogged scenario
Scenes not checked in
Checked in scene
Build Chrome plugin development project
Quickly build Chrome plugin development project (VUE) with VUE-Web-Extension
First, make sure these two are installed
npm install -g @vue/cli
npm install -g @vue/cli-init
I then created the project with Vue-Web-Extension. I selected Vue-Web-Extension as version V1
vue init kocal/vue-web-extension#v1 juejin-auto-sign
Select the features you want on demand (Axios must)
Install Element UI (load on demand)
cd juejin-auto-sign && vue add element
Because the Element UI configuration is written in the Babel section of the package.json file, which overlaps with the project’s original.babelrc configuration file, the configuration for Babel in the package.json file needs to be merged into the.babelrc file
Before the merger
#.babelrc configuration file {"plugins": ["@babel/plugin-proposal-optional-chaining"], "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3, "targets": { // https://jamie.build/last-2-versions "browsers": [" > 0.25% ", "not ie 11", "not op_mini all"]}}}]] # package. The json configuration file {... "babel": { "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] } }
After the merge, remove the Babel part of package.json. The.babelrc configuration file is as follows
Execute yarn build in the root of the project, and it will pack normally
yarn build
So far, the project has been basically completed! It can be formally put into development
Common engineering commands:
- Yarn Build builds the plug-in and outputs it to the dist directory
- Yarn Build-Zip builds a plug-in archive in the form of a plug-in name + version number
yarn watch
Build the plug-in, export it to the dist directory, and refresh it immediately if any changes are made
The key code
MANIFEST. JSON configuration file
The manifest. Json file records the original information of the plug-in, including the basic information of the plug-in (plug-in name, version number, ICON, etc.), the related page of the plug-in (popup, options, background, etc.), and the permissions that the plug-in needs to apply to Chrome
{// Plugin name" name": "Juejin-auto-sign ", // Plugin description" description":" Nugget Sign-in Helper ", // Plugin version number "version": "1.0.0", "Manif_version ": 2, "icons": { "48": "icons/icon.png", "128": "icons/icon.png" }, ...... // Permissions: [" Cookies ", "*://*.juejin.cn ", "WebRequest "," WebRequest "]} Permissions: [" Cookies ", "*://*.juejin.cn ", "WebRequest "," WebRequest "]}
As can be seen in [1], the plugin needs to apply for network permissions WebRequest and WebRequestblocking. These two permissions are related to user login request (POST request). We will explain in detail why these two permissions are required
Popup page
At present, the function of the plug-in is realized in the popup page. The so-called popup page is the page displayed by clicking in the browser plug-in bar
In the case of the Google Translate plugin, the red arrow points to a popup page
There are several pages and scripts for Chrome plugin development
The pages are: popup, optional, background. The display position of different pages on the plug-in is different, and the purpose is also different. At present, you only need to know about the popup page
Scripts include: background.js, content script, etc., and different script declaration cycles are also different
The following shows the main code for the popup page of the check-in helper plug-in
<template> <div class="sign-body"> <div class="sign-image"> <el-avatar size="large" :src="imageUrl"></el-avatar> </div> <div class="sign-text">{{NICKNAME}}</div> <div class="sign-label"> {{NICKNAME}} }</el-tag> </div> <div class="sign-label"> <div class="sign-label"> <div class="sign-label"> <div class="sign-label"> <div class="sign-label" <el-tag size="mini" type="success">{{ continueSignDays }}</el-tag> </div> <div class="sign-btn" v-if="! loading"> <el-button v-if="! Login" type="primary" @click="toLogin"> </el-button> <el-button v-else type="primary" :loading="signing" :disabled="todaySign" @click="toSign">{{ todaySign ? }}</el-button> </div> </div> </template> <script> export default {data() {return {// ImageURL: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', / / nickName nickName: 'null', / / the current ore quantity currentPoint: 0, // ContinuesignDays: 0, // Login: false, // ToDaySign: true, Loading: true, Signing: false,}; },... async mounted() { this.loading = true; Let resp = await getUserInfo(); // verify the validity of cookie this.login =! resp.data.err_no && resp.data.data; if (! this.login) { this.loading = false; return; } // avatar_large; this.imageURL = resp.data.data.avatar_large; this.nickName = resp.data.data.user_name; Resp = await getCurrentPoint(); this.currentPoint = resp.data.data; // await getSignData(); resp = await getSignData(); this.continueSignDays = resp.data.data.cont_count; Resp = await gettoDaySign (); this.todaySign = resp.data.data; this.loading = false; }}; </script>
The main logic is contained in the page mounted stage, which needs to perform a series of operations, including obtaining user information, judging the validity of the cookie, obtaining the user’s current check-in status and reward information, and so on
Ignore a bunch of clumsy \<div\> tags in \<template\>, I just write \<div\> at the front end
Modify the request header
Check-in request /growth_api/v1/check_in is a POST request, and the browser will automatically take the Origin header with the value chrome-extension:// XXXXX. Nuggets will then check the Origin header, Non – nugget Origin will be sent to 403 (Gateway layer checks the source of the request)
At this point, the plug-in needs to modify the Origin field in the request header. However, the Origin field cannot be modified at will
For example, Axios forcing the origin value in the request header does not work, and the plug-in’s console will get an error message. This action is not compliant
At this point, you need to use the permissions of the network request registered in MANIFEST.json
A normally responding request in Chrome will go through the declaration cycle shown in the figure below
If we need to change the request header field, we can change the Origin field by listening for an event before OnBeforeSendHeaders sends the request header. This event listening should run throughout the life of the plug-in, so the code should be written in backdate.js
/ / background. Js file chrome. WebRequest. OnBeforeSendHeaders. AddListener (function (details) {details. RequestHeaders. Push ({ name: 'origin', value: 'https://juejin.cn' }); return { requestHeaders: details.requestHeaders }; }, { urls: ['*://*.juejin.cn/*'] }, ['blocking', 'requestHeaders', 'extraHeaders'] );
The code above you can see, chrome. WebRequest. OnBeforeSendHeaders. AddListener accepts three parameters:
- The listener callback method in which changes to the request header should be placed
- Filter to control the range of listening URLs, where listening on nuggets related requests is selected
-
Meta information (OPT_EXTRainfospec), which is simply, [‘blocking’, ‘requestHeaders’, ‘extraHeaders’] The listener metadata contains [‘blocking’, ‘requestHeaders’, ‘extraHeaders’]. These values represent:
blocking
This means that the callback method is called synchronously, which means that the callback method of one request is executed before the next callback method is turned onrequestHeaders
Represents the parameters of the callback methoddetails
Contains the data for the request headerextraHeaders
This field is kind of magical becauseorigin
The request header is not a quick fix,chrome
If you really want to change it, you have to fill in this field. That’s rightorigin
To take effect
As you can see in the manifest configuration file, the plug-in applies for permissions other than
webRequest
In addition to that,
webRequestBlocking
This permission is added because it is used in the listening method
blocking
Ways of Synchronizing
conclusion
So far, the implementation of the plug-in idea is basically finished, in general, the implementation of the plug-in difficulty is not high, interested can try to try to achieve it
, of course, in the form of a plug-in to realize the sign-in function there is no great extent to improve the efficiency of check-in, or in the server of the best ways to check in regularly, so even if not on the website, also can harvest full ore to draw, but it inevitably user login credentials will be exposed to go out, there may be some security risks, It also lost the point of the Nuggets hosting this event
In case someone gets his cookie and runs to delete his article, it is really want to cry without tears
This time the nuggets sign in the activity personal feel or do can
- The task difficulty is very low, the rules are simple, the activity entrance is obvious
- Sign in the reward is more, a month sign in, should have thousands of ore, should be able to draw dozens of times
The only bad thing is that I smoked for days without a switch, lol