”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 Express、MongoDB 和 Passport.js 实施 JWT 身份验证

使用 Express、MongoDB 和 Passport.js 实施 JWT 身份验证

发布于2024-11-03
浏览:183

Introduction

Secure authentication is a core concept in the development of modern web applications. Authentication is crucial in safeguarding user data and restricting access to certain resources. Authentication involves a series of processes that verify the identity of a user. There are various techniques of authentication, some include:

  • Basic authentication
  • API keys
  • OAuth 2.0
  • JWT (JSON Web Tokens)
  • OpenID Connect

Each technique listed above has pros and cons, refer to article for a detailed explanation.

This article will focus on using JWTs for authentication. According to the docs:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

JWTs are widely used for authentication because of their simplicity and scalability. In this tutorial, you will implement JWT authentication in an Express.js application, using MongoDB and the Passport.js library. By the end of this tutorial, you will create an authentication system with user registration, login, token refresh, and a protected route. You will create the following endpoints:

  • POST /api/v1/auth/register: Registers a new user.
  • POST /api/v1/auth/token: Authenticate a user and return a JWT.
  • POST /api/v1/auth/token/refresh: Refreshes the JWT.
  • POST /api/v1/auth/whoami: Protected route, that retrieves the details of the authentication user.

Authentication Workflow

The diagram below shows the authentication workflow for the application created in this tutorial:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Prerequisites

Before proceeding with the tutorial, ensure you have the following:

  • You have Node.js and NPM installed on your computer.
  • Basic knowledge of Express.js and MongoDB.
  • You have Git installed on your computer.
  • A MongoDB instance that runs locally or remotely (e.g. MongoDB Atlas).
  • A code editor (e.g. VS Code).

Project Setup

For this tutorial, boilerplate code is available in the GitHub repository. Follow these steps to set up the boilerplate code for the application:

  1. Run the command below to clone the repository:

    git clone https://github.com/michaelikoko/express-passport-jwt-auth.git
    
  2. Navigate to the starter directory:

    cd express-passport-jwt-auth/starter
    

    This is the folder structure for the starter directory: Implementing JWT Authentication with Express, MongoDB, and Passport.js

  3. Install the required dependencies:

    npm install
    
  4. Create a .env file in the current directory, and provide the application's port, MongoDB connection string, and the secret key used in signing tokens. The secret key is confidential and should be a random secure string. You can generate a secret key using OpenSSL:

    openssl rand -base64 32 
    

    The .env should look like this:

    PORT=3000
    MONGODB_URI=mongodb srv://<username>:<password>@cluster1.menjafx.mongodb.net
    SECRET=<your-secret-key>
    
  5. Run the development server:

    npm run dev
    
  6. In a web browser, navigate to http://localhost:3000/api/v1/docs/ (replace with the appropriate port number) to access the Swagger documentation. This is an interactive interface that you can use to test the application. Implementing JWT Authentication with Express, MongoDB, and Passport.js

Creating The User Schema

With the boilerplate code all set, you will need to create the schema for the user model. The user schema will be created using the mongoose library, and will include the following fields:

  • email: The email field is unique to each user. It will function as the username.
  • password: This field will contain a hash of the user's password. Storing passwords as plain text in the database poses significant security risks. To learn more about password hashing, you can check out this article.
  • firstname: The user's first name.
  • lastname: The user's last name.

In the models/User.js file, input the following:

const  mongoose  =  require("mongoose");
const  uniqueValidator  =  require("mongoose-unique-validator");

const userSchema = new mongoose.Schema(
  {
    email: {
      type: String,
      required: true,
      unique: true,
      trim: true
    },
    password: {
      type: String,
      required: true,
      trim: true,
      unique: true
    },
    firstName: {
      type: String,
      required: true,
      trim: true,
      minLength: [3, 'First Name too short'],
      maxLength: [50, 'First Name too long']
    },
    lastName: {
      type: String,
      required: true,
      trim: true,
      minLength: [3, 'Last Name too short'],
      maxLength: [50, 'Last Name too long']
    },
  },
  { timestamps: true }
);

userSchema.set('toJSON', {
  transform: (document,returnedObject) => {
    returnedObject.id  =  returnedObject._id.toString()
    delete returnedObject._id
    delete returnedObject.__v
    delete returnedObject.password  //do not reveal password
    delete returnedObject.createdAt
    delete returnedObject.updatedAt
  }
})

userSchema.plugin(uniqueValidator)

module.exports  =  mongoose.model('User', userSchema)

Creating Refresh Token Schema

To improve security, JWT access tokens will be short-lived. When they expire, the client application can use a valid refresh token to get new access tokens. This prevents the user from having to log in every time the access token expires.

In this tutorial, refresh tokens will be stored in the database. This will allow you to securely track and manage issued refresh tokens.

The schema for the refresh token will contain the following fields:

  • token: The refresh token string. In this tutorial, it is a randomly generated UUIDv4 identifier.
  • user: This field references the id of the user assigned to the refresh token. It establishes a many-to-one relationship with the User model.
  • expiryDate: This field indicates when the refresh token will become invalid.

In the models/RefreshToken.js file, input the following:

const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");
const refreshTokenSchema = new mongoose.Schema(
  {
    token: {
      type: String,
      required: true,
      unique: true,
      trim: true,
    },
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User",
    },
    expiryDate: {
      type: Date,
      required: true,
    },
  },
  { timestamps: true }
);

refreshTokenSchema.plugin(uniqueValidator);

module.exports = mongoose.model("RefreshToken", refreshTokenSchema);

Configuring Passport.js

Passport.js is a well-known authentication library for Node.js. Passport.js is described in the docs as:

Simple, unobtrusive authentication for Node.js

Passport.js provides a set of different authentication strategies, such as JWT, and Oauth2, as well as social login using Google, Facebook, GitHub, and many more.

In this tutorial, you will configure the passport-jwt and passport-http strategies.

Install Passport

To make use of the Passport.js library, you need to first install passport and the passport-jwt and passport-http strategies:

npm install passport passport-jwt passport-http

Create Helper Functions

Before configuring Passport.js, you need to create helper functions for hashing and comparing passwords. As stated earlier in the article, a hash of the user's password will be saved in the database. The bcrypt library can be used to hash passwords.

Install bcrypt using:

npm install bcrypt

In the utils/helper.js file, input the following:

const bcrypt = require("bcrypt");
const saltRounds = 10;

async function hashPassword(password) {
  const salt = await bcrypt.genSalt(saltRounds);
  const passwordHash = await bcrypt.hash(password, salt);
  return passwordHash;
}

async function comparePassword(password, hashPassword) {
  return await bcrypt.compare(password, hashPassword);
}

module.exports = {
  hashPassword,
  comparePassword
};

Create Configuration File

In the middleware directory, create a file named passport.js. The file will contain the code necessary for configuring the authentication strategies. The middleware/passport.js file has the following content:

const passport = require("passport");
const PassportJWT = require("passport-jwt");
const PassportHttp = require("passport-http");
const config = require("../utils/config");
const User = require("../models/User");
const helper = require("../utils/helper");

const options = {
  jwtFromRequest: PassportJWT.ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: config.SECRET,
};

passport.use(
  new PassportJWT.Strategy(options, async (payload, done) => {
    try {
      const user = await User.findOne({ _id: payload.id });
      if (user) {
        return done(null, user);
      } else {
        return done(null, false);
      }
    } catch (error) {
      return done(error);
    }
  })
);

passport.use(
  new PassportHttp.BasicStrategy( async (userid, password, done) => {
    try {
      const user = await User.findOne({ email: userid });
      if (!user) {
        return done(null, false);
      }
      const isPasswordCorrect = await helper.comparePassword(password, user.password)
      if (!isPasswordCorrect) {
        return done(null, false);
      }
      return done(null, user);
    } catch (error) {
      return done(error);
    }
  })
);

module.exports = passport;

You start by requiring the passport library, passport-jwt strategy, passport-http strategy, the User schema, the helper functions, and the config object which reads the secret key set in the .env file.

JWT Strategy

To set up an authentication strategy, you pass the strategy instance into the passport.use() method. The passport-jwt strategy instance is constructed using:

new PassportJWT.Strategy(options, verify)

The constructor has two parameters:

  1. options: The options parameter is an object that controls token extraction. The options have several properties, visit the docs for a comprehensive list. In this tutorial, you only made use of the two required object properties:

    • secretOrKey: The value of the secretOrKey property is a string containing the secret key used for signing the token.
    • jwtFromRequest: A function that accepts a request as a parameter, and extracts and returns the JWT. The passport-jwt strategy provides a couple of inbuilt extractors. To extract the token from the authorization header with the scheme 'bearer', you make use of the fromAuthHeaderAsBearerToken() extractor. Visit the docs for all included extractors.
  2. verify: The verify parameter is a function with two parameters verify(payload, done):

    • payload: An object that contains the decoded JWT payload.
    • done: A passport error first callback function accepting arguments done(error, user, info).

    In the verify function, you check if the id provided in the JWT payload matches any user in the database. This is done using User.findOne({ _id: payload.id }).

    If the id belongs to a registered user, you call the done function with no error and the user details:

    return  done(null, user);
    

    If the id doesn't belong to a registered user in the database, you call the done function with no error, and a false value for the user:

    return done(null, false);
    

    If the search fails, and an error occurs, you call the done function with the corresponding value for the error:

    return done(error);
    

    When called successfully, the done function attaches the user's details to the request object.

Basic Strategy

Passport.js HTTP Basic authentication strategy verifies users using a user ID, which is an email in this tutorial, and a password. The passport-http strategy constructors require a verify callback function:

 new  PassportHttp.BasicStrategy(verify)

The verify callback function has three parameters:

  • userid
  • password
  • done

In the verify callback function, you check if the email provided belongs to a registered user. This is done using:

User.findOne({ email: userid })

If the user exists, you then compare the provided password to the stored hashed password. Here, you make use of the comparePassword helper function:

helper.comparePassword(password, user.password)

The done callback function is called appropriately.

Initialize Passport

After creating the configuration, you need to initialize Passport.js authentication modules as middleware in your main application file, app.js.

To initialize Passport.js as a middleware in your application, first require the passport library from the configuration file, /middleware/passport.js. Then, you make use of Passport's built-in middleware function:

 passport.initialize()

Modify the app.js file as follows:

// ...

//import middleware
// ...
const passport = require("./middleware/passport");
// ...

//middleware
// ...
app.use(passport.initialize());
// ...

User Registration Endpoint

In this part of the tutorial, you will create two endpoints:

  • GET /api/v1/auth: An endpoint that lists all users in the database.

  • POST /api/v1/auth/register: An endpoint that allows the registration of new users.

The boilerplate code has already taken care of routing, error handling using express-async-errors, and request body validation using express-validator. This means your main focus will be on the controller's logic.

To begin, require the User schema and the helper functions in the controllers/auth.js file:

const User = require("../models/User");
const helper = require("../utils/helper");
// ...

List Users

In the controllers/auth.js file, add the following lines of code to the listUsers function:

//...
async function listUsers(req, res) {
  const users = await User.find({}).exec();
  return res.status(200).json(users);
}
// ...

The listUsers function is pretty straightforward, it queries and returns all users in the database.

Create Users

The code for creating users is implemented in the createUser function. Edit the controllers/auth.js file as follows:

// ...
async function createUser(req, res) {
  const { email, firstName, lastName, password } = req.body;
  const passwordHash = await helper.hashPassword(password);
  const user = await User.create({
    email,
    firstName,
    lastName,
    password: passwordHash,
  });
  return res.status(201).json(user);
}
// ...

The createUser controller first extracts the email, firstName, lastName, and password from the request body. It then hashes the password provided using the helper.hashPassword function and creates a new user in the database.

Testing the User Registration Endpoint

You can navigate to http://localhost:3000/api/v1/docs/ (ensure the appropriate port number is used) to test the user registration endpoints using Swagger UI.

Creating a new user should appear as follows:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Testing the list user endpoint should show the user you created:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

User Authentication Endpoint

In this step of the tutorial, you will create the user authentication endpoint. The /api/v1/auth/token endpoint allows users to log in to the application by verifying the credentials provided.

More Helper Functions

Before creating the login endpoint, you need to create three more helper functions:

  • issueAccessToken: This function generates and returns a signed JWT. The payload is passed as a parameter.

    You can use the jsonwebtoken library to create JWTs. Install the jsonwebtoken library using:

    npm install jsonwebtoken
    
  • createRefreshToken: This function creates a new refresh token. The user ID is passed as a parameter.

    To generate a random UUIDv4 string as the token value, you can use the uuid library. Install the library using:

    npm install uuid
    
  • verifyRefreshTokenExpiration: This function checks whether a given refresh token is expired.

    Edit the utils/helper.js file as follows:

    const bcrypt = require("bcrypt");
    const jwt = require("jsonwebtoken");
    const config = require("./config");
    const { v4: uuidv4 } = require('uuid'); 
    const RefreshToken = require("../models/RefreshToken");
    
    const saltRounds = 10;
    
    async function hashPassword(password) {
        // ...
    }
    
    async function comparePassword(password, hashPassword) {
    // ...
    }
    
    function issueAccessToken(payload) {
        return jwt.sign(payload, config.SECRET, { expiresIn: 60 * 2}); //2 mins validity 
    }
    
    async function createRefreshToken(userId) {
        let expiryDate = new Date()
        expiryDate.setSeconds(60 * 60 *24) //24 hours validity 
        const token = uuidv4() 
        const refreshToken = await RefreshToken.create({
            token,
            user: userId,
            expiryDate: expiryDate.getTime()
        })
        return refreshToken.token
    }
    
    function verifyRefreshTokenExpiration (token) {
        return token.expiryDate.getTime() 
    
    

Login Controller

The loginUser controller, in the controllers/auth.js file, contains the logic for the user authentication endpoint. Modify the controllers/auth.js file as shown below:

// ...
async function listUsers(req, res) {
    // ...
}

async function createUser(req, res) {
    // ...
}

async function loginUser(req, res) {
  const { email, password } = req.body; 
  const user = await User.findOne({ email });

  if (!user) {
    return res.status(401).json({ error: "Invalid Email" }); 
  }

  const isPasswordCorrect = await helper.comparePassword(
    password,
    user.password
  );

  if (!isPasswordCorrect) {
    return res.status(401).json({ error: "Invalid Password" });
  }

  const payload = {
    email: user.email,
    id: user.id,
  };

  const accessToken = helper.issueAccessToken(payload);
  const refreshToken = await helper.createRefreshToken(user.id);
  return res.status(200).json({
    accessToken,
    refreshToken,
  });
}
// ...

The loginUser controller extracts the login credentials, i.e. email and password from the request body. The function searches for the user in the database with the given email. If no user is found, it returns an error with the 401 Unauthorized status code.

The function proceeds to compare the password provided with the password hash stored in the database using the helper.comparePassword function earlier created. If the passwords don't match, it returns a 401 Unauthorized error, with the appropriate error message.

After the user has been successfully verified, the function creates the payload for the JWT. The payload will contain the user's email and id. It generates a JWT access token using the helper function issueAccessToken passing the payload as a parameter. It also generates a refresh token using the helper function issueRefreshToken. The loginUser controller then returns both tokens as a response.

Testing the User Authentication Endpoint

You can proceed to test the login endpoint using Swagger UI. Passing a valid email and password should give you a response like this:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Token Refresh

As mentioned earlier, access tokens will be short-lived and users will be able to get new access tokens using refresh tokens. This feature will allow users to maintain their authenticated sessions without having to log in again.

In this section, you will write the controller logic for implementing refresh tokens. Add the following code to the controllers/auth.js file:

// ...

const  RefreshToken  =  require("../models/RefreshToken");
async function listUsers(req, res) {
    // ...
}

async function createUser(req, res) {
    // ...
}

async function loginUser(req, res) {
    // ...
}

async function refreshToken(req, res) {
  const { refreshToken: refreshTokenUUID } = req.body; 
  const refreshToken = await RefreshToken.findOne({
    token: refreshTokenUUID,
  }).populate("user");

  if (!refreshToken) {
    return res.status(404).json({ error: "invalid refresh token" 
    });
  }

  const isExpired = helper.verifyRefreshTokenExpiration(refreshToken);

  if (isExpired) {
    await RefreshToken.findByIdAndDelete(refreshToken._id).exec();
    return res.status(403).json({ error: "Refresh token is expired" });
  }

  const payload = {
    email: refreshToken.user.email,
    id: refreshToken.user.id,
  };

  await RefreshToken.findByIdAndDelete(refreshToken._id).exec();
  const newAccessToken = helper.issueAccessToken(payload);
  const newRefreshToken = await helper.createRefreshToken(payload.id);

  return res.status(200).json({
    accessToken: newAccessToken,
    refreshToken: newRefreshToken,
  });
}

// ...

The refreshToken function first extracts the UUIDv4 refresh token passed by the user from the request body. It then searches the database for the token provided by the user. This is done using the RefreshToken.findOne method. The user data associated with the token is retrieved using the .populate("user") method. The user data will be necessary when creating the payload object for a new access token. If the refresh token does not exist in the database, an error with the 404 Not Found status is returned.

The refreshToken controller proceeds to check if the token is expired using the verifyRefreshTokenExpiration helper function. If the token is expired, it is deleted from the database, and an error with 403 Forbidden status is returned.

The function creates the payload object with the user's email and id.

The refresh token rotation technique helps to improve security. It ensures that refresh tokens can only be used once. To invalidate the refresh token after use, the refreshToken function deletes the old refresh token. The function generates a new access token and refresh token using the issueAccessToken and createRefreshToken helper functions. The function then returns the generated tokens to the client.

Testing the Token Refresh Endpoint

You can test the refresh token passing endpoint using Swagger UI. Passing a valid token should give a result that looks like this:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Protected Route

Protected routes are endpoints that can only be accessed by authenticated users. They can be crucial for securing sensitive information and restricting certain actions.

To test the authentication system you just built, you are going to create a protected route. In this tutorial, it is just going to be a simple route that returns the details of the authenticated user.

In the controllers/auth.js file, create the whoami controller function:

// ...

async function listUsers(req, res) {
    // ...
}

async function createUser(req, res) {
    // ...
}

async function loginUser(req, res) {
    // ...
}

async function refreshToken(req, res) {
    // ...
}

async function whoami(req, res) {
  return res.status(200).json(req.user);
}

//...

To use the Passport.js library to create protected routes, add the passport.authenticate middleware is to the route definition. Edit the routes/auth.js as follows:

// ...
const  passport  =  require("../middleware/passport");

//...
router
  .route("/whoami")
  .get(passport.authenticate(["jwt", "basic"], { session: false }), whoami);

module.exports = router;

In the passport.authenticate pass a list of the authentication strategies used as the first parameter. In this application, you made use of the JWT strategy and basic authentication. Therefore, you pass the list: [ "jwt", "basic"].

The { session: false } option tells Passport.js not to maintain a session. This is done because JWT authentication is stateless.

Testing the Protected Route

You can test the protected route using Swagger UI. First, log in to obtain a valid access user token using the /api/v1/auth/token endpoint. Then click on the “Authorize” button in the Swagger UI, pass the access token into the input box under “bearer Auth”, and click the “Authorize” button. This ensures that subsequent requests made with Swagger UI will have the token passed in the request header.

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Testing the /api/v1/auth/whoami endpoint should look like this:

Implementing JWT Authentication with Express, MongoDB, and Passport.js

Conclusion

In this tutorial, you implemented JWT authentication in an Express.js application using the Passport.js library, and MongoDB.

You started by exploring the workflow for JWT authentication. You proceeded to create the necessary schemas. Furthermore, you configured the Passport.js library for both JWT and basic authentication. You also created the controller logic for user registration, user authentication, token refresh, and protected route endpoints. You also tested the endpoints using the Swagger UI interactive interface.

This article should give you a solid foundation for securing APIs built in Express.js using JWT and Passport.js. For further improvements, you should consider sending tokens as HTTP-only cookies, email verification for users, and password reset endpoint.

References

  • Passport.js Documentation

  • MongoDB Documentation

  • Express.js Documentation

  • Mongoose Documentation

  • JWT docs

  • jsonwebtoken package

  • Bcrypt package

  • uuid package

版本声明 本文转载于:https://dev.to/michaelikoko/implementing-jwt-authentication-with-express-mongodb-and-passportjs-3fl7?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 在 JavaScript 中实现点击劫持防御技术
    在 JavaScript 中实现点击劫持防御技术
    点击劫持等复杂攻击的出现使安全成为当今网络世界的首要问题。通过欺骗消费者点击与他们最初看到的内容不同的内容,攻击者部署了一种称为“点击劫持”的邪恶方法,这可能会带来灾难性的后果。此类攻击有可能诱骗人们下载恶意软件、发送私人信息,甚至做他们无意的事情,例如购买任何东西。为了防止此类攻击,JavaScr...
    编程 发布于2024-11-08
  • 为什么我的浮动 Div 不调整后续 Div 的大小?
    为什么我的浮动 Div 不调整后续 Div 的大小?
    Float 不调整 Div 大小之谜当使用 CSS float 时,假设后续元素将左对齐而不是流到新的元素上线。然而,在某些情况下,例如提供的示例,下面的 div 继续跨越整个宽度,而不是从第一个 div 的右侧开始。为了理解这种行为,我们深入研究 float 的复杂性定位。当元素浮动时(在本例中为...
    编程 发布于2024-11-08
  • 使用 PYTHON 将数据导入 MYSQL
    使用 PYTHON 将数据导入 MYSQL
    介绍 手动将数据导入数据库,尤其是当数据库中有多个表时,不仅很烦人,而且还很耗时。通过使用 python 库可以使这变得更容易。 从kaggle下载绘画数据集。绘画数据集由 8 个 csv 文件组成,我们将使用简单的 python 脚本将其导入到数据库中,而不是手动将数据导入到数据...
    编程 发布于2024-11-08
  • MySQL 基本运算符及其应用
    MySQL 基本运算符及其应用
    MySQL 运算符是开发人员的关键工具,可实现精确的数据操作和分析。它们涵盖了一系列功能,包括赋值、数据比较和复杂模式匹配。无论您是处理 JSON 数据还是根据条件过滤记录,了解这些运算符对于高效的数据库管理都至关重要。 本指南介绍了最重要的MySQL运算符,并通过实际示例演示了如何使用它们,使开...
    编程 发布于2024-11-08
  • 如何测试 Cron 作业:完整指南
    如何测试 Cron 作业:完整指南
    Cron 作业在许多系统中对于调度任务、自动化流程和按指定时间间隔运行脚本至关重要。无论您是维护 Web 服务器、自动备份还是运行例行数据导入,cron 作业都能让您的操作顺利运行。但与任何自动化任务一样,它们必须经过彻底测试以确保可靠性和准确性。 在本文中,我们将探讨如何有效地测试 cron 作...
    编程 发布于2024-11-08
  • Next.js 中间件简介:它如何工作并提供示例
    Next.js 中间件简介:它如何工作并提供示例
    我们来谈谈Nextjs中的路由。今天,我们来谈谈最强大的事物中间件之一。 Nextjs 中的中间件提供了一种强大而灵活的方法来拦截来自服务器的请求并控制请求流(重定向、URL 重写)并全局增强身份验证、标头、cookie 持久性等功能。 创建中间件 让我们创建 Middleware ...
    编程 发布于2024-11-08
  • 道具基础知识:第 1 部分
    道具基础知识:第 1 部分
    这是一个关于如何使用道具的初学者友好教程。在阅读之前了解什么是解构以及如何使用/创建组件非常重要。 Props,properties的缩写,props允许我们从父组件向子组件发送信息,还需要注意的是它们可以是任何数据类型。 必须了解为任何组件创建 prop 的语法。在 React 中,您必须使用...
    编程 发布于2024-11-08
  • Hibernate 与 Spring Boot 有何不同?
    Hibernate 与 Spring Boot 有何不同?
    Hibernate 与 Spring Boot 有何不同? Hibernate 和 Spring Boot 都是 Java 生态系统中流行的框架,但它们有不同的用途并具有不同的功能。 休眠 Hibernate 是一个对象关系映射 (ORM) 框架,它允许开发人员使用...
    编程 发布于2024-11-08
  • C++ 如何处理十进制数据类型?
    C++ 如何处理十进制数据类型?
    C 中的十进制数据类型 C 提供了各种数据类型来处理数值,但令人惊讶的是,十进制数据类型本身并不支持。在处理精确的十进制值或与使用十进制格式的系统交互时,这可能是一个限制。实现选项虽然 C 不提供内置十进制类型,但有两种与他们合作的方法:1。 C Decimal TR 扩展:某些编译器(例如 gcc...
    编程 发布于2024-11-08
  • 为什么我的 Python 中的凯撒密码函数只显示最后一个移位的字符?
    为什么我的 Python 中的凯撒密码函数只显示最后一个移位的字符?
    Python 中的凯撒密码函数:加密字符串在 Python 中实现凯撒密码函数时,会出现一个常见问题,即最终的加密文本仅显示最后移动的字符。要解决此问题,有必要了解导致此行为的问题。在提供的代码中,循环迭代明文中的每个字符。对于字母字符,它根据提供的移位值来移位字符的 ASCII 代码。但是,每个移...
    编程 发布于2024-11-08
  • 4 快速​​部署PHP
    4 快速​​部署PHP
    Servbay 已成为轻松配置开发环境的首要工具。在本指南中,我们将演示如何快速、安全地部署 PHP 8.2,强调 Servbay 致力于简化部署过程。 先决条件 开始之前,请确保您的设备上安装了 Servbay。您可以直接从Servbay官方网站下载。安装直观;只需按照提示操作,就...
    编程 发布于2024-11-08
  • AngularJS 指令中的 Replace 属性何时被弃用?
    AngularJS 指令中的 Replace 属性何时被弃用?
    为什么 AngularJS 已弃用指令中的替换属性AngularJS 指令中的替换属性由于其复杂性和更好的出现而被弃用替代方案。根据官方 AngularJS API 文档,在未来的版本中它将默认为 false。弃用的原因AngularJS 团队发现了替换属性的几个问题:困难的语义: 它导致了属性合并...
    编程 发布于2024-11-08
  • 释放 Claude AI:用于经济实惠且灵活的 AI 集成的非官方 API
    释放 Claude AI:用于经济实惠且灵活的 AI 集成的非官方 API
    由 Anthropic 开发的 Claude AI 以其令人印象深刻的能力在人工智能界掀起了波澜。然而,官方 API 对于许多开发人员和小型企业来说可能过于昂贵。这就是我们的非官方 Claude AI API 的用武之地,它提供了一个更实惠、更灵活的解决方案,将 Claude 的力量集成到您的项目中...
    编程 发布于2024-11-08
  • 如何使用时间包确定 Go 中一个月的最后一天?
    如何使用时间包确定 Go 中一个月的最后一天?
    使用 Time.Time 确定给定月份的最后一天处理基于时间的数据时,通常需要确定指定月份的最后一天。无论该月有 28 天、29 天(闰年)还是 30 天或 31 天,这都会使这成为一项具有挑战性的任务。时间包解决方案Go 时间包其日期函数提供了一个方便的解决方案。 Date 的语法为:func D...
    编程 发布于2024-11-08
  • 如何在不支持的浏览器中实现“背景滤镜”效果?
    如何在不支持的浏览器中实现“背景滤镜”效果?
    CSS:为不可用的背景过滤器提供替代方案CSS 中的背景过滤器功能在大多数现代浏览器中仍然无法访问。虽然我们预计其未来的支持,但发现替代解决方案势在必行。实现类似效果的一种方法是采用具有微妙透明度的背景。下面的 CSS 代码演示了这种方法:/* Slightly transparent fallba...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3