You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Sails 1.0后端利用OAuth返回的JWT构建用户会话的最佳实践

针对你的SPA认证方案与Sails 1.0适配问题的解答

嘿,我来帮你一步步理清这个问题:

一、Office-JS-Helpers获取的JWT直接用于后端会话是否可行?

这个方案完全可行,但需要注意几个关键前提:

  • 必须严格验证JWT的合法性:要确认JWT的签名是微软官方公钥签发的,同时检查iss(签发者)、aud(受众)、exp(过期时间)这些Claims是否符合你的应用配置,避免伪造的JWT。
  • 如果你的后端需要自定义用户权限、关联内部用户数据,或者想自主控制Token的有效期,那生成自定义JWT会更灵活:流程是后端验证Office的JWT合法后,根据JWT中的用户信息(比如邮箱、租户ID)查询你的数据库,生成包含自定义Claims的JWT返回给前端,后续前端用这个自定义JWT和后端交互。

两种方案各有优劣:直接用Office JWT减少了后端的Token生成逻辑,但依赖微软的Token有效期;自定义JWT则让你对认证流程有完全的控制权,更适合复杂的业务场景。

二、Sails 1.0 + Passport.js的适配实现步骤

Sails 1.0的配置结构确实和0.11差异很大,下面是适配1.0版本的具体实践:

1. 安装依赖

首先安装所需的包:

npm install passport passport-azure-ad jsonwebtoken @sailshq/connect-redis
  • passport-azure-ad:用于验证微软Azure AD签发的JWT(对应Office 365认证)
  • jsonwebtoken:如果要生成自定义JWT的话需要
  • @sailshq/connect-redis:可选,用于生产环境的会话存储(避免默认内存存储的问题)

2. 创建Passport配置文件

在config/目录下新建passport.js,配置Azure AD的Bearer策略:

const passport = require('passport');
const BearerStrategy = require('passport-azure-ad').BearerStrategy;

module.exports = function (sails) {
  // 配置Azure AD策略参数,这些值从你的Azure应用注册中获取
  const azureADOptions = {
    identityMetadata: `https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}/v2.0/.well-known/openid-configuration`,
    clientID: process.env.AZURE_CLIENT_ID,
    validateIssuer: true,
    issuer: `https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}/v2.0`,
    audience: process.env.AZURE_CLIENT_ID, // 必须和你的应用注册的clientID一致
    loggingLevel: 'warn',
    passReqToCallback: false
  };

  // 验证成功后的回调,获取用户信息
  const verifyCallback = (token, done) => {
    // 这里可以根据token中的用户信息(比如token.upn、token.oid)查询你的数据库
    // 如果用户不存在,可以自动创建;如果存在,返回用户数据
    const user = {
      id: token.oid,
      email: token.upn,
      displayName: token.name
    };
    return done(null, user);
  };

  // 初始化策略
  passport.use(new BearerStrategy(azureADOptions, verifyCallback));

  return {
    passport: passport
  };
};

3. 创建Passport钩子加载中间件

Sails 1.0需要通过钩子来加载Passport中间件,在api/hooks/passport/目录下新建index.js:

module.exports = function (sails) {
  return {
    initialize: async function () {
      const passport = sails.config.passport.passport;
      // 挂载Passport中间件
      sails.app.use(passport.initialize());
      // 如果需要基于会话的认证,启用session中间件
      sails.app.use(passport.session());

      // 序列化用户到会话(如果用会话的话)
      passport.serializeUser((user, done) => {
        done(null, user.id);
      });

      // 从会话反序列化用户
      passport.deserializeUser((id, done) => {
        // 这里根据ID查询数据库获取用户信息
        User.findOne({ id }).exec((err, user) => {
          done(err, user);
        });
      });
    }
  };
};

4. 编写认证控制器

在api/controllers/AuthController.js中创建验证接口,接收前端传来的Office JWT:

const passport = require('passport');
const jwt = require('jsonwebtoken');

module.exports = {
  // 验证Office JWT并处理会话/生成自定义JWT
  verifyOfficeJwt: function (req, res) {
    // 使用passport的策略验证JWT
    passport.authenticate('oauth-bearer', { session: false }, (err, user, info) => {
      if (err || !user) {
        return res.unauthorized({ message: 'Invalid or expired Office JWT', error: info });
      }

      // 方案1:直接创建Sails会话
      req.session.user = user;
      return res.ok({ message: 'Session created successfully', user });

      // 方案2:生成自定义JWT返回给前端
      // const customJwt = jwt.sign(user, process.env.JWT_SECRET, { expiresIn: '24h' });
      // return res.ok({ message: 'Custom JWT generated', token: customJwt, user });
    })(req, res);
  }
};

5. 配置路由

在config/routes.js中添加认证接口的路由:

module.exports.routes = {
  // ...其他路由
  'POST /api/auth/verify-office-jwt': 'AuthController.verifyOfficeJwt'
};

6. 环境变量配置

在config/env/production.js和config/env/development.js中添加你的Azure应用信息和JWT密钥:

module.exports = {
  // ...其他配置
  custom: {
    AZURE_TENANT_ID: '你的租户ID',
    AZURE_CLIENT_ID: '你的应用clientID',
    JWT_SECRET: '强随机字符串,用于签名自定义JWT'
  }
};

最佳实践总结

  • 永远用HTTPS传输JWT,避免明文泄露
  • 生产环境不要用Sails默认的内存会话存储,配置Redis或数据库存储
  • 验证Office JWT时一定要检查所有关键Claims,不要跳过签名验证
  • 如果用自定义JWT,设置合理的过期时间,并且定期轮换签名密钥
  • 前端拿到JWT后,建议存在HttpOnly的Cookie中(如果用会话),或者localStorage中(无状态模式),但要注意XSS防护

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:55:25