Token-based authentication with Angular and Node
Sep 01, 2023 pm 02:01 PMAuthentication is one of the most important parts of any web application. This tutorial discusses token-based authentication systems and how they differ from traditional login systems. By the end of this tutorial, you will see a fully working demo written in Angular and Node.js.
Traditional Authentication System
Before moving on to token-based authentication systems, let’s take a look at traditional authentication systems.
- The user provides username and password in the login form, and then clicks Login.
- After making the request, authenticate the user on the backend by querying the database. If the request is valid, a session is created using the user information obtained from the database, and the session information is returned in the response header so that the session ID is stored in the browser.
- Provides session information for accessing restricted endpoints in the application.
- If the session information is valid, have the user access the specified endpoint and respond with rendered HTML content.
So far, so good. The web application works fine and is able to authenticate users so they can access restricted endpoints. But what happens when you want to develop another client for your application (such as an Android client)? Are you able to authenticate mobile clients and serve restricted content using your current application? As it stands, no. There are two main reasons for this:
- Sessions and cookies have no meaning for mobile applications. You cannot share sessions or cookies created on the server side with mobile clients.
- In the current application, return the rendered HTML. In mobile clients, you need to include something like JSON or XML as the response.
In this case you need a client independent application.
Token-based authentication
In token-based authentication, cookies and sessions are not used. The token will be used to authenticate the user for every request made to the server. Let's redesign the first scenario using token-based authentication.
It will use the following control flow:
- The user provides username and password in the login form, and then clicks Login.
- After making the request, authenticate the user on the backend by querying the database. If the request is valid, a token is created using the user information obtained from the database and then returned in the response header so that we can store the token browser in local storage.
- Provide token information in each request header to access restricted endpoints in your application.
- If the token obtained from the request header information is valid, let the user access the specified endpoint and respond with JSON or XML.
In this case, we are not returning a session or cookie, nor are we returning any HTML content. This means we can use this architecture for any client-specific application. You can see the schema below:
So what is this JWT?
JWT
JWT stands for JSON Web Token and is the token format used in the authorization header. This token helps you design communication between the two systems in a secure manner. For the purposes of this tutorial, we will reformulate JWT as "Bearer Token". A bearer token consists of three parts: header, payload, and signature.
- Header is the part of the token that holds the token type and encryption method, and is also encrypted using Base-64.
- Payload Contains information. You can enter any type of data such as user information, product information, etc., all of which are stored using Base-64 encryption.
- Signature consists of a combination of header, payload, and key. The key must be kept securely on the server side.
You can see the JWT schema and sample token below:
You don't need to implement a bearer token generator, as you can find established packages for many languages. You can see some of them below:
Node.js | https://github.com/auth0/node-jsonwebtoken |
PHP | http://github.com/firebase/php-jwt |
Java | http://github.com/auth0/java-jwt |
紅寶石 | https://github.com/jwt/ruby-jwt |
.NET | https://github.com/auth0/java-jwt |
Python | http://github.com/progrium/pyjwt/ |
A practical example
Having covered some basic information about token-based authentication, we can now move on to a practical example. Take a look at the architecture below, then we'll analyze it in more detail:
- Multiple clients (such as web applications or mobile clients) make requests to the API for a specific purpose.
- Requests are made to services such as
https://api.yourexampleapp.com
. If many people use the application, multiple servers may be needed to serve the requested operations. - Here, the load balancer is used to balance the requests to best suit the backend application servers. When you make a request to
https://api.yourexampleapp.com
, the load balancer first handles the request and then redirects the client to a specific server. - There is an application, and the application is deployed to multiple servers (server-1, server-2, ..., server-n). Whenever a request is made to
https://api.yourexampleapp.com
, the backend application intercepts the request headers and extracts the token information from the Authorization header. This token will be used for database queries. If this token is valid and has the required permissions to access the requested endpoint, it will continue. If not, it will return a 403 response code (indicating forbidden status).
advantage
Token-based authentication has several advantages that solve serious problems. Here are some of them:
Client-independent service
In token-based authentication, the token is transmitted through the request header, rather than persisting the authentication information in the session or cookie. This means there is no state. You can send requests to the server from any type of client that can make HTTP requests.
Content Delivery Network (CDN)
In most current web applications, the view is rendered on the backend and the HTML content is returned to the browser. Front-end logic depends on back-end code.
There is no need to establish such a dependency. This raises several questions. For example, if you're working with a design agency that implements front-end HTML, CSS, and JavaScript, you'll need to migrate that front-end code into back-end code so that some rendering or filling operations can occur. After a while, the HTML content you render will be very different from what the code agency implemented.
In token-based authentication, you can develop your front-end project separately from your back-end code. Your backend code will return a JSON response instead of rendered HTML, and you can put a minified, gzipped version of your frontend code into a CDN. When you visit a web page, the HTML content will be served from the CDN and the page content will be populated by the API service using the token in the Authorization header.
Cookieless session (or no CSRF)
CSRF is a major problem in modern network security because it does not check whether the source of the request is trustworthy. To solve this problem, use a token pool to send this token on every form post. In token-based authentication, the token is used in the authorization header, and CSRF does not contain this information.
Persistent Token Storage??
When a session read, write, or delete operation occurs in an application, it performs file operations in the operating system's temp
folder, at least for the first time. Let's say you have multiple servers and you create a session on the first server. When you make another request and your request falls to another server, the session information will not be there and you will get an "Unauthorized" response. I know, you can solve this problem with sticky sessions. However, in token-based authentication, this situation is solved naturally. There is no sticky session issue as the request token is intercepted on every request on any server.
These are the most common advantages of token-based authentication and communication. This concludes the theoretical and architectural discussion of token-based authentication. It's time to look at a practical example.
Sample Application
You will see two applications that demonstrate token-based authentication:
- Token-based authentication backend
- Token-based authentication frontend
In the back-end project, there will be service implementation, and the service result will be in JSON format. There is no view returned from the service. In the front-end project, there will be an Angular project for the front-end HTML and then the front-end application will be populated by the Angular service to make requests to the back-end service.
Token-based authentication backend
In the back-end project, there are three main files:
- package.json is used for dependency management.
- models/User.js Contains a user model for database operations on users.
- server.js Used for project guidance and request processing.
That's it! This project is very simple so you can easily understand the main concepts without having to delve too deep into it.
{ "name": "angular-restful-auth", "version": "0.0.1", "dependencies": { "body-parser": "^1.20.2", "express": "4.x", "express-jwt": "8.4.1", "jsonwebtoken": "9.0.0", "mongoose": "7.3.1", "morgan": "latest" }, "engines": { "node": ">=0.10.0" } }?
package.json Contains the project's dependencies: express
for MVC, body-parser
for mocking the post Node. Request handling in js, morgan
for request logging, mongoose
for our ORM framework to connect to MongoDB, and jsonwebtoken
is used to create a JWT token using our user model. There is also a property called engines
which indicates that the project was made using Node.js version >= 0.10.0. This is useful for PaaS services like Heroku. We will also discuss this topic in another section.
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const UserSchema = new Schema({ email: String, password: String, token: String }); module.exports = mongoose.model('User', UserSchema);?
We said we would use the user model payload to generate the token. This model helps us perform user operations on MongoDB. In User.js, the user pattern is defined and the user model is created using the mongoose model. The model is ready for database operations.
Our dependencies have been defined, our user model has been defined, so now let's put it all together to build a service that handles specific requests.
// Required Modules const express = require("express"); const morgan = require("morgan"); const bodyParser = require("body-parser"); const jwt = require("jsonwebtoken"); const mongoose = require("mongoose"); const app = express();?
In Node.js, you can use require
to include modules in your project. First, we need to import the necessary modules into the project:
const port = process.env.PORT || 3001; const User = require('./models/User'); // Connect to DB mongoose.connect(process.env.MONGO_URL);?
Our service will be provided through a specific port. You can use it if any port variable is defined in the system environment variables or we have port 3001
defined. After that, the User model is included and a database connection is established for some user operations. Don’t forget to define an environment variable MONGO_URL
for the database connection URL.
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(morgan("dev")); app.use(function(req, res, next) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization'); next(); });?
In the above section, we used Express to make some configurations to simulate HTTP request processing in Node. We allow requests from different domains in order to develop a client-independent system. If you don't allow this, you will trigger CORS (Cross-Origin Request Sharing) errors in your web browser.
-
Access-Control-Allow-Origin
允許所有域。 - 您可以向此服務(wù)發(fā)送
POST
和GET
請(qǐng)求。 -
X-Requested-With
和content-type
標(biāo)頭是允許的。
app.post('/authenticate', async function(req, res) { try { const user = await User.findOne({ email: req.body.email, password: req.body.password }).exec(); if (user) { res.json({ type: true, data: user, token: user.token }); } else { res.json({ type: false, data: "Incorrect email/password" }); } } catch (err) { res.json({ type: false, data: "Error occurred: " + err }); } });?
我們已經(jīng)導(dǎo)入了所有必需的模塊并定義了我們的配置,所以現(xiàn)在是時(shí)候定義請(qǐng)求處理程序了。在上面的代碼中,每當(dāng)你使用用戶名和密碼向 /authenticate
發(fā)出 POST
請(qǐng)求時(shí),你都會(huì)得到一個(gè) JWT
令牌。首先,使用用戶名和密碼處理數(shù)據(jù)庫(kù)查詢。如果用戶存在,則用戶數(shù)據(jù)將與其令牌一起返回。但是如果沒(méi)有與用戶名和/或密碼匹配的用戶怎么辦?
app.post('/signin', async function(req, res) { try { const existingUser = await User.findOne({ email: req.body.email }).exec(); if (existingUser) { res.json({ type: false, data: "User already exists!" }); } else { const userModel = new User(); userModel.email = req.body.email; userModel.password = req.body.password; const savedUser = await userModel.save(); savedUser.token = jwt.sign(savedUser.toObject(), process.env.JWT_SECRET); const updatedUser = await savedUser.save(); res.json({ type: true, data: updatedUser, token: updatedUser.token }); } } catch (err) { res.json({ type: false, data: "Error occurred: " + err }); } });?
當(dāng)您使用用戶名和密碼向 /signin
發(fā)出 POST
請(qǐng)求時(shí),將使用發(fā)布的用戶信息創(chuàng)建一個(gè)新用戶。在 14th
行,您可以看到使用 jsonwebtoken
模塊生成了一個(gè)新的 JSON 令牌,該令牌已分配給 jwt
變量。認(rèn)證部分沒(méi)問(wèn)題。如果我們嘗試訪問(wèn)受限端點(diǎn)怎么辦?我們?nèi)绾卧O(shè)法訪問(wèn)該端點(diǎn)?
app.get('/me', ensureAuthorized, async function(req, res) { try { const user = await User.findOne({ token: req.token }).exec(); res.json({ type: true, data: user }); } catch (err) { res.json({ type: false, data: "Error occurred: " + err }); } });?
當(dāng)您向 /me
發(fā)出 GET
請(qǐng)求時(shí),您將獲得當(dāng)前用戶信息,但為了繼續(xù)請(qǐng)求的端點(diǎn),確保Authorized
函數(shù)將被執(zhí)行。
function ensureAuthorized(req, res, next) { var bearerToken; var bearerHeader = req.headers["authorization"]; if (typeof bearerHeader !== 'undefined') { var bearer = bearerHeader.split(" "); bearerToken = bearer[1]; req.token = bearerToken; next(); } else { res.send(403); } }?
在該函數(shù)中,攔截請(qǐng)求頭,并提取authorization
頭。如果此標(biāo)頭中存在承載令牌,則該令牌將分配給 req.token
以便在整個(gè)請(qǐng)求中使用,并且可以使用 next( )
。如果令牌不存在,您將收到 403(禁止)響應(yīng)。讓我們回到處理程序 /me
,并使用 req.token
使用此令牌獲取用戶數(shù)據(jù)。每當(dāng)您創(chuàng)建新用戶時(shí),都會(huì)生成一個(gè)令牌并將其保存在數(shù)據(jù)庫(kù)的用戶模型中。這些令牌是獨(dú)一無(wú)二的。
對(duì)于這個(gè)簡(jiǎn)單的項(xiàng)目,我們只有三個(gè)處理程序。之后,您將看到:
process.on('uncaughtException', function(err) { console.log(err); });?
如果發(fā)生錯(cuò)誤,Node.js 應(yīng)用程序可能會(huì)崩潰。使用上面的代碼,可以防止崩潰,并在控制臺(tái)中打印錯(cuò)誤日志。最后,我們可以使用以下代碼片段啟動(dòng)服務(wù)器。
// Start Server app.listen(port, function () { console.log( "Express server listening on port " + port); });?
總結(jié)一下:
- 模塊已導(dǎo)入。
- 配置已完成。
- 已定義請(qǐng)求處理程序。
- 定義中間件是為了攔截受限端點(diǎn)。
- 服務(wù)器已啟動(dòng)。
我們已經(jīng)完成了后端服務(wù)。為了讓多個(gè)客戶端可以使用它,您可以將這個(gè)簡(jiǎn)單的服務(wù)器應(yīng)用程序部署到您的服務(wù)器上,或者也可以部署在 Heroku 中。項(xiàng)目根文件夾中有一個(gè)名為 Procfile
的文件。讓我們?cè)?Heroku 中部署我們的服務(wù)。
Heroku 部署
您可以從此 GitHub 存儲(chǔ)庫(kù)克隆后端項(xiàng)目。
我不會(huì)討論如何在 Heroku 中創(chuàng)建應(yīng)用程序;如果您之前沒(méi)有創(chuàng)建過(guò) Heroku 應(yīng)用程序,可以參考這篇文章來(lái)創(chuàng)建 Heroku 應(yīng)用程序。創(chuàng)建 Heroku 應(yīng)用程序后,您可以使用以下命令將目標(biāo)添加到當(dāng)前項(xiàng)目:
git remote add heroku <your_heroku_git_url>
現(xiàn)在您已經(jīng)克隆了一個(gè)項(xiàng)目并添加了一個(gè)目標(biāo)。在 git add
和 git commit
之后,您可以通過(guò)執(zhí)行 git push heroku master
將代碼推送到 Heroku。當(dāng)您成功推送項(xiàng)目時(shí),Heroku 將執(zhí)行 npm install
命令將依賴項(xiàng)下載到 Heroku 上的 temp
文件夾中。之后,它將啟動(dòng)您的應(yīng)用程序,您可以使用 HTTP 協(xié)議訪問(wèn)您的服務(wù)。
基于令牌的-auth-frontend
在前端項(xiàng)目中,您將看到一個(gè) Angular 項(xiàng)目。在這里,我只提及前端項(xiàng)目中的主要部分,因?yàn)?Angular 不是一個(gè)教程可以涵蓋的內(nèi)容。
您可以從此 GitHub 存儲(chǔ)庫(kù)克隆該項(xiàng)目。在此項(xiàng)目中,您將看到以下文件夾結(jié)構(gòu):
我們擁有三個(gè)組件——注冊(cè)、配置文件和登錄——以及一個(gè)身份驗(yàn)證服務(wù)。
您的app.component.html 如下所示:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrap demo</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"> </head> <body> <nav class="navbar navbar-expand-lg bg-body-tertiary"> <div class="container-fluid"> <a class="navbar-brand" href="#">Home</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item"><a class="nav-link" routerLink="/profile">Me</a></li> <li class="nav-item"><a class="nav-link" routerLink="/login">Signin</a></li> <li class="nav-item"><a class="nav-link" routerLink="/signup">Signup</a></li> <li class="nav-item"><a class="nav-link" (click)="logout()">Logout</a></li> </ul> </div> </div> </nav> <div class="container"> <router-outlet></router-outlet> </div> </body> </html>?
在主組件文件中,<router-outlet></router-outlet>
?定義各個(gè)組件的路由。
在 auth.service.ts 文件中,我們定義 AuthService
類,該類通過(guò) API 調(diào)用來(lái)處理身份驗(yàn)證,以登錄、驗(yàn)證 Node.js 應(yīng)用程序的 API 端點(diǎn)。
import { Injectable } from '@angular/core'; import { HttpClient,HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class AuthService { private apiUrl = 'your_node_app_url'; public token: string =''; constructor(private http: HttpClient) { } signin(username: string, password: string): Observable<any> { const data = { username, password }; return this.http.post(`${this.apiUrl}/signin`, data); } authenticate(email: string, password: string): Observable<any> { const data = { email, password }; console.log(data) return this.http.post(`${this.apiUrl}/authenticate`, data) .pipe( tap((response:any) => { this.token = response.data.token; // Store the received token localStorage.setItem('token',this.token) console.log(this.token) }) ); } profile(): Observable<any> { const headers = this.createHeaders(); return this.http.get(`${this.apiUrl}/me`,{ headers }); } private createHeaders(): HttpHeaders { let headers = new HttpHeaders({ 'Content-Type': 'application/json', }); if (this.token) { headers = headers.append('Authorization', `Bearer ${this.token}`); } return headers; } logout(): void { localStorage.removeItem('token'); } }
在 authenticate()
方法中,我們向 API 發(fā)送 POST 請(qǐng)求并對(duì)用戶進(jìn)行身份驗(yàn)證。從響應(yīng)中,我們提取令牌并將其存儲(chǔ)在服務(wù)的 this.token
屬性和瀏覽器的 localStorage
中,然后將響應(yīng)作為 Observable
返回。
在 profile()
方法中,我們通過(guò)在 Authorization 標(biāo)頭中包含令牌來(lái)發(fā)出 GET 請(qǐng)求以獲取用戶詳細(xì)信息。
createHeaders()
方法在發(fā)出經(jīng)過(guò)身份驗(yàn)證的 API 請(qǐng)求時(shí)創(chuàng)建包含身份驗(yàn)證令牌的 HTTP 標(biāo)頭。當(dāng)用戶擁有有效令牌時(shí),它會(huì)添加一個(gè)授權(quán)標(biāo)頭。該令牌允許后端 API 對(duì)用戶進(jìn)行身份驗(yàn)證。
如果身份驗(yàn)證成功,用戶令牌將存儲(chǔ)在本地存儲(chǔ)中以供后續(xù)請(qǐng)求使用。該令牌也可供所有組件使用。如果身份驗(yàn)證失敗,我們會(huì)顯示一條錯(cuò)誤消息。
不要忘記將服務(wù) URL 放入上面代碼中的 baseUrl
中。當(dāng)您將服務(wù)部署到 Heroku 時(shí),您將獲得類似 appname.herokuapp.com
的服務(wù) URL。在上面的代碼中,您將設(shè)置 var baseUrl = "appname.herokuapp.com"
。
注銷功能從本地存儲(chǔ)中刪除令牌。
在 signup.component.ts
文件中,我們實(shí)現(xiàn)了 signup ()
方法,該方法獲取用戶提交的電子郵件和密碼并創(chuàng)建一個(gè)新用戶。
import { Component } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-signup', templateUrl: './signup.component.html', styleUrls: ['./signup.component.css'] }) export class SignupComponent { password: string = ''; email: string = ''; constructor(private authService:AuthService){} signup(): void { this.authService.signin(this.email, this.password).subscribe( (response) => { // success response console.log('Authentication successful', response); }, (error) => { // error response console.error('Authentication error', error); } ); } }? login.component.ts 文件看起來(lái)與注冊(cè)組件類似。 ?
import { Component } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent { email: string = ''; password: string = ''; constructor(private authService: AuthService) {} login(): void { this.authService.authenticate(this.email, this.password).subscribe( (response) => { // success response console.log('Signin successful', response); }, (error) => { // error response console.error('Signin error', error); } ); } }
配置文件組件使用用戶令牌來(lái)獲取用戶的詳細(xì)信息。每當(dāng)您向后端的服務(wù)發(fā)出請(qǐng)求時(shí),都需要將此令牌放入標(biāo)頭中。 profile.component.ts 如下所示:
import { Component } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-profile', templateUrl: './profile.component.html', styleUrls: ['./profile.component.css'] }) export class ProfileComponent { myDetails: any; constructor(private authService: AuthService) { } ngOnInit(): void { this.getProfileData(); } getProfileData(): void { this.authService.me().subscribe( (response: any) => { this.myDetails = response; console.log('User Data:', this.myDetails); }, (error: any) => { console.error('Error retrieving profile data'); } ); }?
在上面的代碼中,每個(gè)請(qǐng)求都會(huì)被攔截,并在標(biāo)頭中放入授權(quán)標(biāo)頭和值。然后,我們將用戶詳細(xì)信息傳遞到 profile.component.html 模板。
<h2>User profile </h2> <div class="row"> <div class="col-lg-12"> <p>{{myDetails.data.id}}</p> <p>{{myDetails.data.email}}</p> </div> </div>
最后,我們?cè)?app.routing.module.ts 中定義路由。
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { LoginComponent } from './login/login.component'; import { ProfileComponent } from './profile/profile.component'; import { SignupComponent } from './signup/signup.component'; const routes: Routes = [ {path:'signup' , component:SignupComponent}, {path:'login' , component:LoginComponent}, { path: 'profile', component: ProfileComponent }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }?
從上面的代碼中您可以很容易地理解,當(dāng)您轉(zhuǎn)到/時(shí),將呈現(xiàn)app.component.html頁(yè)面。另一個(gè)例子:如果您轉(zhuǎn)到/signup,則會(huì)呈現(xiàn)signup.component.html。這個(gè)渲染操作將在瀏覽器中完成,而不是在服務(wù)器端。
結(jié)論
基于令牌的身份驗(yàn)證系統(tǒng)可幫助您在開(kāi)發(fā)獨(dú)立于客戶端的服務(wù)時(shí)構(gòu)建身份驗(yàn)證/授權(quán)系統(tǒng)。通過(guò)使用這項(xiàng)技術(shù),您將只需專注于您的服務(wù)(或 API)。
身份驗(yàn)證/授權(quán)部分將由基于令牌的身份驗(yàn)證系統(tǒng)作為服務(wù)前面的一層進(jìn)行處理。您可以從任何客戶端(例如網(wǎng)絡(luò)瀏覽器、Android、iOS 或桌面客戶端)訪問(wèn)和使用服務(wù)。
The above is the detailed content of Token-based authentication with Angular and Node. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Angular.js is a freely accessible JavaScript platform for creating dynamic applications. It allows you to express various aspects of your application quickly and clearly by extending the syntax of HTML as a template language. Angular.js provides a range of tools to help you write, update and test your code. Additionally, it provides many features such as routing and form management. This guide will discuss how to install Angular on Ubuntu24. First, you need to install Node.js. Node.js is a JavaScript running environment based on the ChromeV8 engine that allows you to run JavaScript code on the server side. To be in Ub

In iOS 17, Apple introduced several new privacy and security features to its mobile operating system, one of which is the ability to require two-step authentication for private browsing tabs in Safari. Here's how it works and how to turn it off. On an iPhone or iPad running iOS 17 or iPadOS 17, if you have any Private Browsing tab open in Safari and then exit the session or app, Apple's browser now requires Face ID/TouchID authentication or a passcode to access again they. In other words, if someone gets their hands on your iPhone or iPad while it's unlocked, they still won't be able to view it without knowing your passcode

Single sign-on (SSO) is an authentication mechanism that allows users to authenticate across multiple applications and sites using a single set of credentials, such as a username and password. This mechanism can improve user experience and efficiency while also enhancing security. In PHP, implementing single sign-on requires some specific methods. Below we will introduce how to implement single sign-on in PHP. We will divide it into the following steps: Create a user authentication center (AuthenticationCenter) using OAuth2

Detailed explanation and installation guide for PiNetwork nodes This article will introduce the PiNetwork ecosystem in detail - Pi nodes, a key role in the PiNetwork ecosystem, and provide complete steps for installation and configuration. After the launch of the PiNetwork blockchain test network, Pi nodes have become an important part of many pioneers actively participating in the testing, preparing for the upcoming main network release. If you don’t know PiNetwork yet, please refer to what is Picoin? What is the price for listing? Pi usage, mining and security analysis. What is PiNetwork? The PiNetwork project started in 2019 and owns its exclusive cryptocurrency Pi Coin. The project aims to create a one that everyone can participate

Implementing user authentication using middleware in the Slim framework With the development of web applications, user authentication has become a crucial feature. In order to protect users' personal information and sensitive data, we need a reliable method to verify the user's identity. In this article, we will introduce how to implement user authentication using the Slim framework’s middleware. The Slim framework is a lightweight PHP framework that provides a simple and fast way to build web applications. One of the powerful features is the middle

Authentication is one of the most important parts of any web application. This tutorial discusses token-based authentication systems and how they differ from traditional login systems. By the end of this tutorial, you will see a fully working demo written in Angular and Node.js. Traditional Authentication Systems Before moving on to token-based authentication systems, let’s take a look at traditional authentication systems. The user provides their username and password in the login form and clicks Login. After making the request, authenticate the user on the backend by querying the database. If the request is valid, a session is created using the user information obtained from the database, and the session information is returned in the response header so that the session ID is stored in the browser. Provides access to applications subject to

The default display behavior for components in the Angular framework is not for block-level elements. This design choice promotes encapsulation of component styles and encourages developers to consciously define how each component is displayed. By explicitly setting the CSS property display, the display of Angular components can be fully controlled to achieve the desired layout and responsiveness.

With the rapid development of the Internet and mobile Internet, more and more applications require authentication and permission control, and JWT (JSON Web Token), as a lightweight authentication and authorization mechanism, is widely used in WEB applications. Beego is an MVC framework based on the Go language, which has the advantages of efficiency, simplicity, and scalability. This article will introduce how to use JWT to implement authentication in Beego. 1. Introduction to JWT JSONWebToken (JWT) is a
