Why token based auth?
This paragraph is excerpted from
English original
After discussing some basic knowledge about token-based authentication, let's look at an example. Take a look at the following points, then we will carefully analyze it:
Multiple terminals, such as a Web application, a mobile terminal, etc., send a specific request to the API.
Requests such as https://api.yourexampleapp.com are sent to the service tier. If many people use this app, multiple servers are required to respond to these request actions.
At this point, load balancing is used to balance requests to achieve optimal backend application services. When you send a request to https://api.yourexampleapp.com, the outermost load balancer processes the request and then redirects to the specified server.
An application may be deployed on multiple servers (server-1, Server-2, ..., server-n). When a request is sent to Https://api.yourexampleapp.com, the backend app intercepts the request header and extracts the token information from the Authentication header. Use this token to query the database. If the token is valid and has the required permission to request the terminal data, the request will continue. If it is not valid, a 403 status code (indicating a denied state) is returned.
Token-based authentication has several advantages when it comes to solving tricky problems:
-
Client independent Services. In token-based authentication, token is transmitted through the request header, rather than storing the authentication information in a session or cookie. This means that there is no state. You can send requests to the server from any terminal that can send HTTP requests.
-
CDN. In most current applications, the view is rendered on the backend, and the HTML content is returned to the browser. The front-end logic relies on the backend code. It's really not necessary to rely on this. Moreover, there are several problems. For example, you work with a design agency, the designer helps you with the front-end html,css and JavaScript, you need to get the front-end code and port it to your backend code, for the purpose of rendering. After several changes, the HTML content you render may differ greatly from the designer's code. In token-based authentication, you can develop front-end projects that are completely independent of back-end code. The backend code returns a JSON instead of rendering the HTML, and you can put the minimized, compressed code on the CDN. When you visit a Web page, the HTML content is serviced by a CDN, and the page content is populated by the API service that uses tokens from the authentication header.
-
No cookie-session (or no CSRF). CSRF is a pain point in contemporary web security because it does not check whether a request source is trustworthy. To solve this problem, a token pool is used to send related tokens each time a form request is made. In token-based authentication, there is already a token applied to the authentication header, and CSRF does not contain that information.
-
Persistent the Token Store. When a session is read, written, or deleted in the application, a file operation occurs in the operating system's Temp folder, at least for the first time. Suppose you have more than one server and the session is created on the first service. When you send the request again and the request falls on another server, the session information does not exist and will receive an "unauthenticated" response. I know that you can solve this problem through a sticky session. However, in token-based authentication, the problem is naturally solved. There is no sticky session problem because the token of this request is intercepted in each request sent to the server.
These are the most obvious advantages of token-based authentication and communication. This is where the theory and architecture based on token authentication comes in. The example below.
This paragraph would have wanted to write on their own, but write the content themselves, save some time
JWT Encryption and decryption
The JWT represents the JSON Web token, which is a token format for authenticating the head. This token helps you to deliver information in a secure way between the two systems. For instructional purposes, we'll take the JWT as "bearer token" for the moment. A bearer token consists of three parts: Header,payload,signature.
The header is part of the token and is used to store the token type and encoding, usually using BASE-64 encoding.
The payload contains information. You can store any kind of information, such as user information, product information, etc. They are all stored using the Base-64 encoding method. The signature includes a mixture of header,payload and keys. The key must be securely bunkers stored on the server side.
Nodejs implementation of the JWT code
Http://github.com/auth0/node-jsonwebtoken
3 Main methods
Jwt.sign
Jwt.verify
Jwt.decode
Requires careful handling of keys in multithreaded or clustered.
The time to decrypt an object is much smaller than the cost of querying the database, and the only possibility is that the token is valid for validation, at very low cost.
Elegant writing authorizing token acquisition
In the app/routes/api/index.js.
authrouter.post ('/auth ', function (req, res, next) { user.one ({username: req.body.username},function (Err, user) { if (err) throw err; console.log (user); if (!user) { res.json ({ success: false, message: ' authentication failed, user name not found ' }); } else if (user) { // check password if (User.password != req.body.password) { res.json ({ success: false, message: ' authentication failed, Password error ' }); } else { // Create token var token = jwt.sign (user, ' App.get (supeRsecret) ', { ' expiresInMinutes ': 1440 // set expiration Time }); // json format returns Token res.json ({ success: true, message: ' enjoy your token! ', token: token }); } } });
Test
Curl-d "username=sang&password=000000" Http://127.0.0.1:3019/api/auth
Return
{"Success": TRUE, "message": "Enjoy Your token!", "token": " Eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjfawqioii1ntc4mzjkzjk0ztfjn2yymdjmytvlnguilcj1c2vybmftzsi6innhbmcilcjwyxnzd29yzci6 Ijawmdawmcisimf2yxrhcii6iiisinbob25lx251bwjlcii6iiisimfkzhjlc3mioiiilcjfx3yiojb9.wv5za6gpjsmi346o625_ 8fxfom4dj1cwnuezg10zqg4 "}%
Route processing
In app/routes/api/groups.js
.
var express = require (' Express '); var router = Express. Router (); var $ = require ('.. /.. /controllers/groups_controller ') var $middlewares = require (' mount-middlewares '); Router.get ('/list ', $ Middlewares.check_api_token, $.api.list); module.exports = router;
Core code
Router.get ('/list ', $middlewares. Check_api_token, $.api.list);
Description
Use of $middlewares.check_api_token middleware
Core business logic in $.api.list
As with other Express routing usages, none of his
Middleware $middlewares.check_api_token
/*! * moajs middle * copyright (c) 2015-2019 alfred sang <[ Email protected]> * mit licensed */var jwt = require (' Jsonwebtoken ' );//used to create and confirm user Information summary// Check user session module.exports = function (Req, res, next) { console.log (' Check post information or URL query parameters or header information '); //check post information or URL query parameters or header information var token = req.body.token | | req.query.token | | req.headers[' X-access-token ']; // analysis token if (token) { // Confirm token jwt.verify (token, ' App.get (supersecret) ', function (err, decoded) { if (err) { return res.json ({ success: false, message: ' token information error. ') }); } else { // Save the decoded message to the request if it is not a problem, and use it for the following route req.api_user = decoded; console.dir (Req.api_user); next (); } }); } else { // returns an error if there is no token return res.status (403). Send ({ success: false, message: ' did not provide token! ' }); }};
This is easy to explain, as long as the parameter has token or X-access-token in the header information, we assume it is an API interface,
When the validation is passed, the token's Decode object, which is the previously encrypted user object, is returned and saved asreq.api_user
Business code
In app/controllers/groups_controller.js
.
exports.api = { list: function (Req, res, next) { console.log (req.method + ' /groups => list, query: ' + json.stringify (Req.query)); var user_id = req.api_user . _id; group.query ({ower_id: user_id}, function (err, groups) { console.log (groups); res.json ({ data:{ groups : groups }, status:{ code : 0, msg : ' Success ' } }) }); }}
Let scaffold generate code and APIs coexist, clear
Explain
Test interface
Then let's test it.
GET request
URL = http://127.0.0.1:3019/api/groups/list
Parameter token
{"Data": {"groups": [{"_id": "557d32a282f9ddcc76a540e8", "name": "SJKLJKL", "desc": "2323", "ower_id": " 557832df94e1c7f202fa5e4e "," Users ":" "," Is_public ":", "__v": 0},{"_id": "557d32b082f9ddcc76a540e9", "name": "Sjkljkl "," desc ":" 2323 "," ower_id ":" 557832df94e1c7f202fa5e4e "," Users ":" "," Is_public ":", "__v": 0},{"_id": " 557d32f082f9ddcc76a540ea "," name ":" SJKLJKL "," desc ":" 2323 "," ower_id ":" 557832df94e1c7f202fa5e4e "," Users ":" "," Is_ Public ":", "__v": 0},{"_id": "557d33804f5905de78e1c25a", "name": "SJKLJKL", "desc": "2323", "ower_id": " 557832df94e1c7f202fa5e4e "," Users ":" "," Is_public ":", "__v": 0},{"_id": "557d33984f5905de78e1c25b", "name": "Anan", " Desc ":" 2323 "," ower_id ":" 557832df94e1c7f202fa5e4e "," Users ":" 2323 "," is_public ":" 232 "," __v ": 0}]}," status ": {" Code " : 0, "MSG": "Success"}}
Models, queries, and other
Models, queries, and others, still dominated by Mongoosedao.
Basically enough.
If you still want to play a bit higher, you can add a service layer and put multiple model operations inside.
Summarize
Write the API later, you can play this way
1) app/routes/api/
create the corresponding API files in the directory, such as Groups.js,topics.js,users.js, etc.
2) then in the corresponding controller, add
Exports.api = {aa:function (req, res, next) {var user_id = req.api_user._id; }, Bb:function (req, res, next) {var user_id = req.api_user._id; }}
3) Simple write-point model of the Query method can be
Isn't it simple?
What if we provide the generator later?
Think about is very good, good will continue to be beautiful ~
Fill it up.
End of full text
Nodejs RESTful Architecture Practice API Chapter (RPM)