It is but a step from thinking to doing

When the front-end logon succeeds, the back-end returns a token, which the front-end stores locally and carries with it for identification in all subsequent interface requests… Many people know this concept, but if you just know the concept, this article will hopefully take you through it and walk you through the ins and outs of token step-by-step practice code.

1. What is token?

In the simplest terms, tokens are back-end generated, encrypted strings that can be used to represent a user’s identity. How does the back end normally generate such a token? The most popular way to generate tokens is JWT (JSON Web Token). If you want to know what JWT is, read on. JWT generates one after the server authenticates

{" name ":" snail ", "role" : "handsome boy" and "maturity" : "on March 8, 2022 0 point 0"}Copy the code

This JSON object is returned to the front-end, but for security reasons, it is obviously dangerous to return the JSON object directly (the user can tamper with the data), so the token generated by JWT is also encrypted and looks like this:

Note: The token itself does not have a line break. The line break is just for effect. The three different colors represent the token

  • Header
  • Payload
  • Signature (= Signature)

Those of you who have no idea of these three terms have already opened a search engine

2. Why use tokens?

Today is goddess day, your girlfriend added a cart full of goods to her Taobao shopping cart, she threw the cart address to you, can you see her shopping cart list directly on your computer? Of course not. You have to log on to her taobao account didn’t have permission to see a shopping cart list, here is a typical access control, if taobao background doesn’t recognize the current user is on a visit to the shopping cart page you girlfriend, listing data is not displayed, if present, it is conceivable that you are the most panic ~ ~ ~ so token, also known as the token, It’s designed for user identification

3. Prepare the front and rear ends

Let’s create a JWT folder and create a front end project and a back end project in it. I’m just lazy enough to create a project with vue3

Current directory structure:

With vantUI we start by writing a front-end login page

<! -- src/views/Login.vue --> <template> <van-form @submit="onSubmit" class="login-form"> <van-cell-group inset> <van-field V-model ="username" name="username" label=" placeholder "placeholder=" username" :rules="[{required: true, message: }]" /> <van-field v-model="password" type="password" name="password" label=" password" placeholder=" password" :rules=" { "/> </van-cell-group> <div style="margin: 16px; < <van-button round block type="primary" native type="submit"> </van-button> </div> </van-form> </template> <script> import { ref } from 'vue'; export default { setup() { const username = ref(''); const password = ref(''); const onSubmit = (values) => { console.log('submit', values); }; return { username, password, onSubmit, }; }}; </script> <style lang="less"> .login-form{ margin-top: 30px; } </style>Copy the code

After the route /login page is configured, the page is displayed normally

Click login to get the account and password entered by the user, so we will initiate the login interface request. Before sending the request, the front end will install an AXIos, and then create the directory SRC > API > index.js

// src > api > index.js import axios from 'axios' import router from '.. / router 'const BASE_URL =' http://localhost:3000 '. / / request intercept axios interceptors. Request. Use ((config) = > {let jwtToken = Window. The localStorage. The getItem (' jwtToken) if (jwtToken) {/ / carry token config in the request header. The headers. Authorization = jwtToken} Return the config}) / / response to intercept axios. Interceptors. Response. Use (res = > {/ / intercept an error condition if (res) data) code! == 0) { return Promise.reject(res.data.error) } return res }, If (error.response.status >= 400 && error.response.status < 500) { router.push('/login') } return Promise.reject(error.response.data.error) }) export function post(url, body) { return axios.post(BASE_URL+url, body) }Copy the code

Create user.js in the API folder and wrap a login function:

// src > api > user.js
import { post } from './index'

export function login(body) {
  return post('/login', body).then(res => res.data)
}
Copy the code

To introduce the wrapped function to the login page use:

<script> import { ref } from 'vue'; import { login } from '.. / API /user // export default {setup() {const username = ref(''); const password = ref(''); const onSubmit = (values) => { console.log('submit', values); // add code login(values).then(res => {console.log(res); })}; return { username, password, onSubmit, }; }}; </script>Copy the code

Now that we have the front-end ready, all we need to do is provide the login interface on the back-end. NPM I Koa koa-router koA2-cors koa-bodyParser is required to install the project. Go to the server > app.js folder

// server > app.js const Koa = require(' Koa ') const cors = require('koa2-cors' require('koa-bodyparser'); Const app = new koa () app.use(bodyParser()); // Const app = new koa () app.use(bodyParser()); app.use(cors()); App.listen (3000, () => console.log(' service started on port 3000 '))Copy the code

Next, use the routes to define the interface, create the Routes folder under the server folder, and create user.js in routes

const router = require('koa-router')() router.post('/login', (ctx) => { let user = ctx.request.body console.log(user); If (1) {ctx.body = {code: 0, data: user.username,}} else {ctx.body = {code: 1, data: Router. Post ('/home', (CTX) => {try {CTX. Body = {code: 0, data: "got home page" } } catch (error) { ctx.body = { code: 1, data: error } } }) module.exports = routerCopy the code

Enabling routing again

// server > app.js const Koa = require(' Koa ') const cors = require('koa2-cors' require('koa-bodyparser'); // const userRouter = require('./routes/user') const app = new koa () app.use(bodyParser()); app.use(cors()); + app. Use (userRouter. Routes (), userRouter. AllowedMethods ()) app. Listen (3000, () = > console. The log (' service has been started on port 3000))Copy the code

Run Nodemon App.js and you will see that the project has started normally. Next we will go to the page and enter any account and password and click the login button and you will see the backend print

Having successfully retrieved the parameters passed by the front end, this is the core of this article

When the backend receives the parameters passed by the front-end login request, it normally goes to the database to verify that the current account and password are correct. If correct, the front-end should return a successful login and a token. Then how does the backend generate the token? Earlier we mentioned JWT, which is what we use to generate tokens

4. How does the backend generate tokens

We need to install jsonWebToken in the backend project, execute NPM I jsonWebToken, create utils folder under server, and create jwt.js file inside utils

// server > utils > jwt.js const JWT = require('jsonwebtoken') Function sign(option) {return jwt.sign(option, '666', {expiresIn: Module. Exports = {sign}Copy the code

Go back to the routing file user.js and use JWT

// server > routes > user.js const router = require('koa-router')() + const jwt = require('.. /utils/jwt') router.post('/login', (ctx) => { let user = ctx.request.body console.log(user); / / simulation database inspection if (1) {+ let jwtToken = JWT. Sign ({id: '1023', the username: CTX. Request. The body. The username, the admin: true}) + console.log(jwtToken); Ctx. body = {code: 0, data: 'success', token: jwtToken}} else {ctx.body = {code: 1, data: 'username or password error'}}})Copy the code

Generate a token using the user ID (in this case, the fake data is written down) and the user name, and set to administrator privileges, and the front-end sends the login request again as you will see

The backend has generated a time-sensitive token, and the next step is to respond to this token in the login interface

If (1) {let jwtToken = jwt.sign({id: '1023', username: ctx.request.body.username, admin: true}) console.log(jwtToken); Ctx. body = {code: 0, data: user.username, + token: jwtToken}} // Omit some codeCopy the code

Initiate the front-end login request again, which we can see in the browser console

All that’s left is for the front end to retrieve the token and store it in local storage

<script> import {ref} from 'vue'; import { login } from '.. Import {useRouter} from 'vue-router'; import {useRouter} from 'vue-router'; export default { setup() { const router = useRouter() const username = ref(''); const password = ref(''); Const onSubmit = (values) = > {login (values). Then (res = > {/ / new code window. LocalStorage. SetItem (' jwtToken ', res.token) router.push('/home') }) }; return { username, password, onSubmit, }; }}; </script> // omit some codeCopy the code

Each request from the front-end will carry the token in the request header. Do you think it is over at this point? No, no, no, there is another key question. The backend needs to verify whether the user is logged in or invalid when requesting data from the home page. In other words, the backend needs to verify whether the token in the request header is valid

5. Verify the validity and permission of JWT

Let’s simply create a home page

// src > views > Home.vue <template> <div>Home</div> </template> <script> import { onMounted } from 'vue' import { home } from '.. /api/user' export default { setup() { onMounted(() => { home().then(res => { console.log(res); }) }) return { } } } </script> <style> </style>Copy the code

And configure the route of the Home page, and then encapsulate the request function to be used in the Home page in the API user.js

// src > api > user.js import { post } from './index' export function login(body) { return post('/login', Then (res => res.data)} export function home(body) {return post('/home', body).then(res => res.data)}Copy the code

When you come back to the browser /home page

We’ve already written about the back-end interface, but this last one needs to come back to the back-end code

// server > utils > jwt.js const JWT = require('jsonwebtoken') Function sign(option) {return jwt.sign(option, '666', {expiresIn: Let verify = (isAdmin) => (CTX, Next) = > {/ / to get to the front end pass more than token let jwtToken = CTX. The req. Headers. The authorization if (jwtToken) {/ / check the legitimacy of the token jwt.verify(jwtToken, '666', function(err, decoded) { if (err) { ctx.body = { status: 401, message: }} else {if (isAdmin) {let {admin} = decoded if (admin) {next()} else {ctx.body = {status: 401, message: 'You are not an administrator! Not enough permissions! ' } } } else { next() } } }); } else {ctx.body = {status: 401, message: 'please provide token'}} module. Exports = {sign, verify}Copy the code

Here we double wrap the jwt.verify method, throw the verify function, and use it in the routing interface

// server > routes > user.js // Verify () router.post('/home', jwt.verify(), (CTX) => {try {ctx.body = {code: 0, data: "got home page" } } catch (error) { ctx.body = { code: 1, data: error } } })Copy the code

This will trigger JWT validation when the /home interface is requested. Let’s see what happens

After manually deleting the token stored locally in the browser, refresh the page under /home

Now you don’t get data back until you log in, and when we log back in, go to the /home page, wait a minute, and refresh the home page again, you’ll see the same thing

Milk!! The token will expire when no data has been requested by the backend within the specified time

conclusion

Congratulations, you have a deeper understanding of token. If you think it is helpful, welcome to like your attention. The source address is here

Article Reference:

Ruan Yifeng’s network log

Cookie, Session, Token, JWT