搜尋
首頁CMS教程&#&按使用Angular和Node進行基於令牌的身份驗證

使用Angular和Node進行基於令牌的身份驗證

Sep 01, 2023 pm 02:01 PM
angularnode身份驗證

使用Angular和Node進行基於令牌的身份驗證

身份驗證是任何 Web 應用程式中最重要的部分之一。本教程討論基於令牌的身份驗證系統以及它們與傳統登入系統的差異。在本教程結束時,您將看到一個用 Angular 和 Node.js 編寫的完整工作演示。

傳統身分驗證系統

在繼續基於令牌的身份驗證系統之前,讓我們先來看看傳統的身份驗證系統。

  1. 使用者在登入表單中提供使用者名稱密碼,然後點擊登入
  2. 發出請求後,透過查詢資料庫在後端驗證使用者。如果請求有效,則使用從資料庫中獲取的使用者資訊建立會話,然後在回應頭中傳回會話訊息,以便將會話ID儲存在瀏覽器中。
  3. 提供用於存取應用程式中受限端點的會話資訊。
  4. 如果會話資訊有效,則讓使用者存取指定端點,並使用呈現的 HTML 內容進行回應。

使用Angular和Node進行基於令牌的身份驗證

#到目前為止一切都很好。 Web 應用程式運作良好,並且能夠對使用者進行身份驗證,以便他們可以存取受限端點。但是,當您想為您的應用程式開發另一個客戶端(例如 Android 用戶端)時會發生什麼情況?您是否能夠使用目前的應用程式來驗證行動用戶端並提供受限制的內容?就目前情況而言,沒有。造成這種情況的主要原因有兩個:

  1. 會話和 Cookie 對於行動應用程式沒有意義。您無法與行動用戶端分享在伺服器端建立的會話或 Cookie。
  2. 在目前應用程式中,傳回呈現的 HTML。在行動用戶端中,您需要包含 JSON 或 XML 等內容作為回應。

在這種情況下,您需要一個獨立於客戶端的應用程式。

基於令牌的身份驗證

在基於令牌的身份驗證中,不會使用 cookie 和會話。令牌將用於對向伺服器發出的每個請求進行使用者身份驗證。讓我們使用基於令牌的身份驗證重新設計第一個場景。

它將使用以下控制流程:

  1. 使用者在登入表單中提供使用者名稱密碼,然後點擊登入
  2. 發出請求後,透過在資料庫中查詢來驗證後端的使用者。如果請求有效,則使用從資料庫獲取的使用者資訊建立令牌,然後在回應標頭中傳回該訊息,以便我們可以將令牌瀏覽器儲存在本地儲存中。
  3. 在每個請求標頭中提供令牌訊息,以存取應用程式中的受限端點。
  4. 如果從請求標頭資訊中取得的令牌有效,則讓使用者存取指定端點,並使用 JSON 或 XML 進行回應。

在這種情況下,我們沒有回傳會話或cookie,也沒有回傳任何HTML內容。這意味著我們可以將此架構用於任何客戶端的特定應用程式。您可以看到下面的架構架構:

使用Angular和Node進行基於令牌的身份驗證

#那麼這個 JWT 是什麼?

JWT

JWT 代表 JSON Web 令牌,是授權標頭中使用的令牌格式。此令牌可協助您以安全的方式設計兩個系統之間的通訊。出於本教學的目的,我們將 JWT 重新表述為「不記名令牌」。不記名令牌由三個部分組成:標頭、負載和簽名。

  • 標頭是令牌中保存令牌類型和加密方法的部分,也是使用 Base-64 進行加密的。
  • 有效負載包含資訊。您可以輸入任何類型的數據,例如使用者資訊、產品資訊等,所有這些數據都使用 Base-64 加密進行儲存。
  • 簽章由標頭、負載和金鑰的組合組成。密鑰必須安全地保存在伺服器端。

您可以在下面看到 JWT 架構和範例令牌:

使用Angular和Node進行基於令牌的身份驗證

#您不需要實作不記名令牌產生器,因為您可以找到多種語言的已建立套件。您可以在下面看到其中一些:

##PHPhttp://github.com/firebase/php-jwtJavahttp://github.com/auth0/java-jwt紅寶石https://github.com/jwt/ruby-jwt ###。網### https://github.com/auth0/java-jwthttp://github.com/progrium/pyjwt/

一個實際範例

介紹了有關基於令牌的身份驗證的一些基本資訊後,我們現在可以繼續討論一個實際範例。看看下面的架構,然後我們將更詳細地分析它:

使用Angular和Node進行基於令牌的身份驗證

#
  1. 多個用戶端(例如網路應用程式或行動用戶端)出於特定目的向 API 發出請求。
  2. 要求是向 https://api.yourexampleapp.com 等服務發出的。如果很多人使用該應用程序,則可能需要多個伺服器來提供請求的操作。
  3. 這裡,負載平衡器用於平衡請求,以最適合後端的應用程式伺服器。當您向 https://api.yourexampleapp.com 發出請求時,負載平衡器會先處理請求,然後會將客戶端重新導向到特定伺服器。
  4. 有一個應用程序,並且該應用程式部署到多台伺服器(server-1、server-2、...、server-n)。每當向 https://api.yourexampleapp.com 發出請求時,後端應用程式都會攔截請求標頭並從授權標頭中提取令牌資訊。將使用此令牌進行資料庫查詢。如果此令牌有效且具有存取所請求端點所需的權限,則它將繼續。如果沒有,它將傳回 403 回應代碼(表示禁止狀態)。

優點

基於令牌的身份驗證具有解決嚴重問題的多個優點。以下是其中的一些:

獨立於客戶端的服務

在基於令牌的身份驗證中,令牌透過請求標頭傳輸,而不是將身份驗證資訊保留在會話或 cookie 中。這意味著沒有狀態。您可以從任何類型的可以發出 HTTP 請求的客戶端向伺服器發送請求。

內容傳遞網路 (CDN)

在目前的大多數 Web 應用程式中,視圖在後端呈現,HTML 內容返回瀏覽器。前端邏輯依賴後端程式碼。

沒有必要建立這樣的依賴關係。這帶來了幾個問題。例如,如果您正在與實作前端 HTML、CSS 和 JavaScript 的設計機構合作,您需要將該前端程式碼遷移到後端程式碼中,以便進行一些渲染或填滿操作。一段時間後,您呈現的 HTML 內容將與程式碼機構實現的內容有很大不同。

在基於令牌的身份驗證中,您可以與後端程式碼分開開發前端專案。您的後端程式碼將傳回 JSON 回應,而不是渲染的 HTML,而且您可以將前端程式碼的縮小、gzip 版本放入 CDN 中。當您造訪網頁時,HTML 內容將從 CDN 提供,並且頁面內容將由 API 服務使用授權標頭中的令牌填充。

CSRF 是現代網路安全的一個主要問題,因為它不會檢查請求來源是否可信。為了解決這個問題,使用令牌池在每個表單貼文上發送該令牌。在基於令牌的身份驗證中,令牌用於授權標頭,而 CSRF 不包含該資訊。

持久令牌儲存

當應用程式中進行會話讀取、寫入或刪除操作時,它會在作業系統的 temp 資料夾中進行檔案操作,至少第一次是這樣。假設您有多個伺服器,並且在第一台伺服器上建立了一個會話。當您發出另一個請求並且您的請求落入另一台伺服器時,會話資訊將不存在並且將得到「未經授權」的回應。我知道,你可以透過黏性會話來解決這個問題。然而,在基於令牌的認證中,這種情況自然就解決了。不存在黏性會話問題,因為請求令牌在任何伺服器上的每個請求上都會被攔截。

這些是基於令牌的身份驗證和通訊的最常見優點。關於基於令牌的身份驗證的理論和架構討論就到此結束。是時候看一個實際例子了。

範例應用程式

您將看到兩個應用程式來演示基於令牌的身份驗證:

  1. 基於令牌的身份驗證後端
  2. 基於令牌的身份驗證前端

在後端專案中,會有服務的實現,服務結果將是JSON格式。服務中沒有返回視圖。在前端專案中,將有一個用於前端 HTML 的 Angular 項目,然後前端應用程式將由 Angular 服務填充,以向後端服務發出請求。

基於令牌的身份驗證後端

在後端專案中,主要有三個檔案:

  • package.json 用於依賴管理。
  • models/User.js 包含一個使用者模型,用於對使用者進行資料庫操作。
  • server.js 用於專案引導和請求處理。

就是這樣!這個項目非常簡單,因此您無需深入研究即可輕鬆理解主要概念。

{
    "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 包含專案的依賴: express 用於MVC,body-parser 用於模擬post Node. js 中的請求處理,morgan 用於請求日誌記錄,mongoose 用於我們的ORM 框架連接到MongoDB,和jsonwebtoken 用於使用我們的使用者模型建立JWT 令牌。還有一個名為 engines 的屬性,表示該專案是使用 Node.js 版本 >= 0.10.0 製作的。這對於 Heroku 等 PaaS 服務很有用。我們還將在另一節中討論主題。

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const UserSchema = new Schema({
  email: String,
  password: String,
  token: String
});

module.exports = mongoose.model('User', UserSchema);
 

我們說過我們將使用使用者模型有效負載產生令牌。這個模型幫助我們對MongoDB進行使用者操作。在User.js中,定義了使用者模式並使用貓鼬模型建立了使用者模型。該模型已準備好進行資料庫操作。

我們的依賴關係已經定義,我們的使用者模型也已經定義,所以現在讓我們將所有這些組合起來建構一個用於處理特定請求的服務。

// 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();
 

在 Node.js 中,您可以使用 require 在專案中包含模組。首先,我們需要將必要的模組導入到專案中:

const port = process.env.PORT || 3001;
const User     = require('./models/User');

// Connect to DB
mongoose.connect(process.env.MONGO_URL);
 

我們的服務將透過特定連接埠提供服務。如果系統環境變數中定義了任何連接埠變量,則可以使用它,或者我們定義了連接埠 3001。之後,包含了User模型,並建立了資料庫連接,以進行一些使用者操作。不要忘記為資料庫連接 URL 定義一個環境變數 MONGO_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();
});

 

在上面的部分中,我們使用 Express 進行了一些配置來模擬 Node 中的 HTTP 請求處理。我們允許來自不同網域的請求,以便開發獨立於客戶端的系統。如果您不允許這樣做,您將在網頁瀏覽器中觸發 CORS(跨來源請求共用)錯誤。

  • Access-Control-Allow-Origin 允许所有域。
  • 您可以向此服务发送 POSTGET 请求。
  • X-Requested-Withcontent-type 标头是允许的。
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
      });
    }
  });
 

我们已经导入了所有必需的模块并定义了我们的配置,所以现在是时候定义请求处理程序了。在上面的代码中,每当你使用用户名和密码向 /authenticate 发出 POST 请求时,你都会得到一个 JWT 令牌。首先,使用用户名和密码处理数据库查询。如果用户存在,则用户数据将与其令牌一起返回。但是如果没有与用户名和/或密码匹配的用户怎么办?

 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
      });
    }
  });
 

当您使用用户名和密码向 /signin 发出 POST 请求时,将使用发布的用户信息创建一个新用户。在 14th 行,您可以看到使用 jsonwebtoken 模块生成了一个新的 JSON 令牌,该令牌已分配给 jwt 变量。认证部分没问题。如果我们尝试访问受限端点怎么办?我们如何设法访问该端点?

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
      });
    }
  });
 

当您向 /me 发出 GET 请求时,您将获得当前用户信息,但为了继续请求的端点,确保Authorized函数将被执行。

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);
    }
}
 

在该函数中,拦截请求头,并提取authorization头。如果此标头中存在承载令牌,则该令牌将分配给 req.token 以便在整个请求中使用,并且可以使用 next( )。如果令牌不存在,您将收到 403(禁止)响应。让我们回到处理程序 /me,并使用 req.token 使用此令牌获取用户数据。每当您创建新用户时,都会生成一个令牌并将其保存在数据库的用户模型中。这些令牌是独一无二的。

对于这个简单的项目,我们只有三个处理程序。之后,您将看到:

process.on('uncaughtException', function(err) {
    console.log(err);
});
 

如果发生错误,Node.js 应用程序可能会崩溃。使用上面的代码,可以防止崩溃,并在控制台中打印错误日志。最后,我们可以使用以下代码片段启动服务器。

// Start Server
app.listen(port, function () {
    console.log( "Express server listening on port " + port);
});
 

总结一下:

  • 模块已导入。
  • 配置已完成。
  • 已定义请求处理程序。
  • 定义中间件是为了拦截受限端点。
  • 服务器已启动。

我们已经完成了后端服务。为了让多个客户端可以使用它,您可以将这个简单的服务器应用程序部署到您的服务器上,或者也可以部署在 Heroku 中。项目根文件夹中有一个名为 Procfile 的文件。让我们在 Heroku 中部署我们的服务。

Heroku 部署

您可以从此 GitHub 存储库克隆后端项目。

我不会讨论如何在 Heroku 中创建应用程序;如果您之前没有创建过 Heroku 应用程序,可以参考这篇文章来创建 Heroku 应用程序。创建 Heroku 应用程序后,您可以使用以下命令将目标添加到当前项目:

git remote add heroku <your_heroku_git_url>

现在您已经克隆了一个项目并添加了一个目标。在 git addgit commit 之后,您可以通过执行 git push heroku master 将代码推送到 Heroku。当您成功推送项目时,Heroku 将执行 npm install 命令将依赖项下载到 Heroku 上的 temp 文件夹中。之后,它将启动您的应用程序,您可以使用 HTTP 协议访问您的服务。

基于令牌的-auth-frontend

在前端项目中,您将看到一个 Angular 项目。在这里,我只提及前端项目中的主要部分,因为 Angular 不是一个教程可以涵盖的内容。

您可以从此 GitHub 存储库克隆该项目。在此项目中,您将看到以下文件夹结构:

使用Angular和Node進行基於令牌的身份驗證

我们拥有三个组件——注册、配置文件和登录——以及一个身份验证服务。

您的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> 定义各个组件的路由。

auth.service.ts 文件中,我们定义 AuthService 类,该类通过 API 调用来处理身份验证,以登录、验证 Node.js 应用程序的 API 端点。

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 发送 POST 请求并对用户进行身份验证。从响应中,我们提取令牌并将其存储在服务的 this.token 属性和浏览器的 localStorage 中,然后将响应作为 Observable 返回。

profile() 方法中,我们通过在 Authorization 标头中包含令牌来发出 GET 请求以获取用户详细信息。

createHeaders() 方法在发出经过身份验证的 API 请求时创建包含身份验证令牌的 HTTP 标头。当用户拥有有效令牌时,它会添加一个授权标头。该令牌允许后端 API 对用户进行身份验证。

如果身份验证成功,用户令牌将存储在本地存储中以供后续请求使用。该令牌也可供所有组件使用。如果身份验证失败,我们会显示一条错误消息。

不要忘记将服务 URL 放入上面代码中的 baseUrl 中。当您将服务部署到 Heroku 时,您将获得类似 appname.herokuapp.com 的服务 URL。在上面的代码中,您将设置 var baseUrl = "appname.herokuapp.com"

注销功能从本地存储中删除令牌。

signup.component.ts 文件中,我们实现了 signup () 方法,该方法获取用户提交的电子邮件和密码并创建一个新用户。

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 文件看起来与注册组件类似。  
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);
      }
    );
  }
}

配置文件组件使用用户令牌来获取用户的详细信息。每当您向后端的服务发出请求时,都需要将此令牌放入标头中。 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');
      }
    );
  }
 

在上面的代码中,每个请求都会被拦截,并在标头中放入授权标头和值。然后,我们将用户详细信息传递到 profile.component.html 模板。

<h2 id="User-profile">User profile </h2>

<div class="row">
    <div class="col-lg-12">
        <p>{{myDetails.data.id}}</p>
        <p>{{myDetails.data.email}}</p>
    </div>
</div>

最后,我们在 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 { }
 

从上面的代码中您可以很容易地理解,当您转到/时,将呈现app.component.html页面。另一个例子:如果您转到/signup,则会呈现signup.component.html。这个渲染操作将在浏览器中完成,而不是在服务器端。

结论

基于令牌的身份验证系统可帮助您在开发独立于客户端的服务时构建身份验证/授权系统。通过使用这项技术,您将只需专注于您的服务(或 API)。

身份验证/授权部分将由基于令牌的身份验证系统作为服务前面的一层进行处理。您可以从任何客户端(例如网络浏览器、Android、iOS 或桌面客户端)访问和使用服务。

Node.js https://github.com/auth0/node-jsonwebtoken
#
#
#
# ###Python###

以上是使用Angular和Node進行基於令牌的身份驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何輕鬆地將博客從 WordPress.com 移至 WordPress.org如何輕鬆地將博客從 WordPress.com 移至 WordPress.orgApr 18, 2025 am 11:33 AM

您想將博客從 WordPress.com 移至 WordPress.org 嗎? 許多初學者從 WordPress.com 開始,但很快意識到其局限性,並希望切換到自託管 WordPress.org 平台。 在本分步指南中,我們將向您展示如何正確地將博客從 WordPress.com 移動到 WordPress.org。 為什麼從 WordPress.com 遷移到 WordPress.org? WordPress.com 允許任何人通過創建帳戶來

如何使用 IFTTT 自動化 WordPress 和社交媒體(及更多)如何使用 IFTTT 自動化 WordPress 和社交媒體(及更多)Apr 18, 2025 am 11:27 AM

您是否正在尋找自動化 WordPress 網站和社交媒體帳戶的方法? 通過自動化,您將能夠在 Facebook、Twitter、LinkedIn、Instagram 等平台上自動分享您的 WordPress 博客文章或更新。 在本文中,我們將向您展示如何使用 IFTTT、Zapier 和 Uncanny Automator 輕鬆實現 WordPress 和社交媒體的自動化。 為什麼要自動化 WordPress 和社交媒體? 自動化您的WordPre

如何修復 WordPress 中的自定義菜單項限制如何修復 WordPress 中的自定義菜單項限制Apr 18, 2025 am 11:18 AM

就在幾天前,我們的一位用戶報告了一個不尋常的問題。問題是他達到了自定義菜單項的限制。達到菜單項限制後他保存的任何內容都將根本無法保存。我們從未聽說過這個問題,因此我們決定在本地安裝上嘗試一下。創建了 200 多個菜單項並保存。效果很好。將 100 個項目移至下拉列表中,保存效果非常好。那時我們就知道這與服務器有關。經過進一步研究,似乎還有許多其他人也遇到了同樣的問題。深入挖掘後,我們發現了一張 trac 票證 ( #14134 ) 強調了這個問題。在閱讀了非常

如何在 WordPress 中將自定義元字段添加到自定義分類法如何在 WordPress 中將自定義元字段添加到自定義分類法Apr 18, 2025 am 11:11 AM

您需要將自定義元字段添加到 WordPress 中的自定義分類法嗎? 自定義分類法可讓您組織除類別和標籤之外的內容。有時添加其他字段來描述它們很有用。 在本文中,我們將向您展示如何將其他元字段添加到他們創建的分類法中。 何時應將自定義元字段添加到自定義分類法? 當您在WordPress 網站上創建新內容時,您可以使用兩種默認分類法(類別和標籤)對其進行組織。 一些網站受益於自定義分類法的使用。這些允許您以其他方式對內容進行排序。 例如,

如何使用 Windows Live Writer 遠程發佈到 WordPress如何使用 Windows Live Writer 遠程發佈到 WordPressApr 18, 2025 am 11:02 AM

Windows live writer 是一款多功能工具,可讓您直接從桌面將帖子發佈到 WordPress 博客上。這意味著您根本不需要登錄 WordPress 管理面板來更新您的博客。在本教程中,我將向您展示如何使用 Windows Live Writer 為您的 WordPress 博客啟用桌面發布。 如何在 WordPress 上設置 Windows Live Writer 第 1 步: 要通過 Windows Live Writer 在 WordPr

如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕Apr 18, 2025 am 10:52 AM

最近,我們的一位用戶報告了一個非常奇怪的安裝問題。寫帖子時,他們看不到自己寫的任何內容。因為帖子編輯器的文字是白色的。更重要的是,所有可視化編輯器按鈕都丟失了,並且從可視化切換到 HTML 的功能也不起作用。在本文中,我們將向您展示如何修復 WordPress 可視化編輯器中的白色文本和缺失按鈕問題。 初學者註意事項:如果您正在尋找可能在其他網站的屏幕截圖中看到的隱藏按鈕,那麼您可能正在尋找廚房水槽。您必須單擊廚房水槽圖標才能看到其他選項,例如下劃線、從單詞複製等。

如何在 WordPress 中顯示用戶電子郵件中的頭像如何在 WordPress 中顯示用戶電子郵件中的頭像Apr 18, 2025 am 10:51 AM

您想在 WordPress 中顯示用戶電子郵件中的頭像嗎? Gravatar 是一項將用戶的電子郵件地址連接到在線頭像的網絡服務。 WordPress 會自動在評論部分顯示訪問者的頭像,但您可能也想將它們添加到網站的其他區域。 在本文中,我們將向您展示如何在 WordPress 中顯示用戶電子郵件中的頭像。 什麼是 Gravatar 以及為什麼要顯示它? Gravatar代表全球認可的頭像,它允許人們將圖片鏈接到他們的電子郵件地址。 如果網站支

如何更改 WordPress 中的默認媒體上傳位置如何更改 WordPress 中的默認媒體上傳位置Apr 18, 2025 am 10:47 AM

您想更改 WordPress 中的默認媒體上傳位置嗎? 將媒體文件移動到其他文件夾可以提高網站的速度和性能,並幫助您更快地創建備份。它還使您可以自由地以最適合您的方式組織文件。 在本文中,我們將向您展示如何更改 WordPress 中的默認媒體上傳位置。 為什麼要更改默認媒體上傳位置? 默認情況下,WordPress 將所有圖像和其他媒體文件存儲在 /wp-content/uploads/ 文件夾中。 在此文件夾中,您將找到不同年份和月份的子

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器