You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Passport-JWT认证Hyperledger Composer REST API并限制注册用户访问

刚好之前帮朋友实现过类似的需求,用Passport-JWT把Hyperledger Composer的REST端点保护起来,用户数据存在MySQL里,只允许注册用户访问。给你梳理一下完整的实现步骤,都是亲测能跑通的:

1. 先搭好依赖环境

首先得安装需要的npm包,Passport-JWT、MySQL驱动、密码哈希工具这些都不能少:

npm install passport passport-jwt mysql2 bcryptjs dotenv
2. 配置MySQL用户存储

先在MySQL里创建用户表,密码一定要用哈希存储,绝对不能明文保存:

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL, -- 存储bcrypt哈希后的密码
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

然后写个MySQL操作的工具文件db.js,用来查询用户信息:

const mysql = require('mysql2/promise');
require('dotenv').config();

// 创建数据库连接池,避免频繁创建销毁连接
const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  connectionLimit: 10
});

// 根据用户名查询用户
async function getUserByUsername(username) {
  const [rows] = await pool.execute('SELECT * FROM users WHERE username = ?', [username]);
  return rows[0];
}

module.exports = { getUserByUsername };
3. 配置Passport-JWT验证策略

接下来写Passport的JWT配置文件passport-config.js,定义JWT的提取方式、验证密钥,以及如何从MySQL验证用户:

const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const { getUserByUsername } = require('./db');
require('dotenv').config();

const opts = {
  // 从请求头的Authorization字段提取Bearer Token
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  // JWT的密钥,存在.env文件里保密,别硬编码
  secretOrKey: process.env.JWT_SECRET
};

passport.use(new JwtStrategy(opts, async (jwtPayload, done) => {
  try {
    // 根据JWT载荷里的用户名查询数据库
    const user = await getUserByUsername(jwtPayload.username);
    if (user) {
      // 找到用户,验证通过
      return done(null, user);
    }
    // 没找到用户,验证失败
    return done(null, false);
  } catch (err) {
    return done(err, false);
  }
}));

module.exports = passport;
4. 给Composer REST Server添加自定义中间件

Composer REST Server支持添加自定义Express中间件,我们把Passport验证逻辑加进去,同时新增一个登录接口用来生成JWT。写个middleware.js

const express = require('express');
const passport = require('./passport-config');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { getUserByUsername } = require('./db');
const router = express.Router();

// 登录接口:用户提交用户名密码,验证成功后返回JWT
router.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body;
    const user = await getUserByUsername(username);
    
    if (!user) {
      return res.status(401).json({ message: '用户名或密码错误' });
    }
    
    // 验证密码哈希是否匹配
    const isPasswordMatch = await bcrypt.compare(password, user.password);
    if (!isPasswordMatch) {
      return res.status(401).json({ message: '用户名或密码错误' });
    }
    
    // 生成JWT,有效期设为1小时(可根据需求调整)
    const token = jwt.sign(
      { username: user.username },
      process.env.JWT_SECRET,
      { expiresIn: '1h' }
    );
    
    res.json({ token: `Bearer ${token}` });
  } catch (err) {
    res.status(500).json({ message: '服务器内部错误' });
  }
});

module.exports = function (app) {
  // 先挂载登录接口,这个接口不需要验证
  app.use(router);
  
  // 初始化Passport
  app.use(passport.initialize());
  
  // 把JWT验证中间件应用到所有/api开头的端点(Composer生成的REST接口默认是/api前缀)
  app.use('/api', passport.authenticate('jwt', { session: false }));
};
5. 启动Composer REST Server并加载中间件

启动的时候用-m参数指定我们写的中间件文件:

composer-rest-server -c admin@your-network-name -n never -w true -m ./middleware.js

记得把admin@your-network-name替换成你自己的Composer网络卡片名称。

6. 测试验证流程
  1. 注册用户:可以写个简单的注册接口,或者手动在MySQL里插入用户数据,密码要用bcrypt哈希生成,比如:
const bcrypt = require('bcryptjs');
console.log(bcrypt.hashSync('your-password', 10)); // 把生成的哈希值插入数据库
  1. 获取JWT:调用POST /login接口,提交用户名和密码,拿到返回的token。
  2. 访问受保护端点:访问Composer的REST接口(比如GET /api/Asset),在请求头里加上Authorization: Bearer <你的token>,就能正常访问;如果不带token或者token无效,会返回401未授权。
一些注意事项
  • 所有敏感配置(数据库信息、JWT密钥)都要放在.env文件里,绝对不要硬编码到代码中。
  • JWT的有效期根据业务需求调整,不要太长也不要太短。
  • 如果只需要保护部分端点,可以修改中间件的路由匹配规则,比如只保护/api/transactions而不是全部/api前缀的接口。

内容的提问来源于stack exchange,提问作者Honey Shah

火山引擎 最新活动