对于同一条船上的任何人......
服务器中间件似乎没有减少它,但普通中间件可以。认为这可能对某人有用...
在我的nuxt.config.js 中,我定义了 API 的身份验证参数并设置了路由器应该使用的中间件。这些实际上是在运行时从.env 文件加载的:
// Public variables
publicRuntimeConfig: {
apiUrl: process.env.API_URL,
name: process.env.APP_NAME
},
// Private variables
privateRuntimeConfig: {
apiClientId: process.env.API_CLIENT,
apiClientSecret: process.env.API_SECRET,
},
// Apply global middleware to our routing.
router: {
middleware: [
'bearer-token'
],
},
现在是中间件。我在中间件文件夹中创建了一个名为bearer-token.ts 的文件,它使用上面的配置自动启用它。事实证明,在这个执行阶段,您实际上可以通过检查process.server 是否为真来检查我们是处于服务器级别还是客户端级别。只要我们在服务器级别,我们就可以使用节点的fs 包来操作文件系统。
这是我的“已完成”中间件(在 typescript 中)...请注意,我正在使用 Vuex 来存储我生成的密钥,这允许我将生成的不记名令牌推送给用户。我还根据令牌到期更新生成文件的修改时间,以便我可以轻松检查令牌何时需要重新生成,从而节省对 oAuth 服务器的过多调用。
import {Context} from '@nuxt/types';
const getToken = (context: Context) => {
const axios = require('axios');
return axios.post('/oauth/token', {
grant_type: 'client_credentials',
client_id: context.$config.apiClientId,
client_secret: context.$config.apiClientSecret,
scope: ''
}, {
baseURL: context.$config.apiUrl,
headers: {'Accept': 'application/json'}
});
}
export default function (context: Context) {
// only perform this at the server level.
if (process.server) {
// set parameters needed.
const fileName = './.apiToken',
timestamp = Date.now(),
fs = require('fs'),
promise = new Promise(async (resolve, reject) => {
try {
// get our stored files timestamps.
const data = fs.statSync(fileName);
// is our file timestamp in the future?
if (Date.now() < data.mtimeMs) {
// resolve our token from our file.
resolve(fs.readFileSync(fileName).toString());
return;
}
} catch (err) {
// ignore this error (file not found)
}
try {
// grab our token from the oAuth server,
// we'll reduce the expiry timestamp by 10 mins
// to reduce near expiring tokens.
const res = await getToken(context),
expiryTime = timestamp + (res.data.expires_in - (60 * 10));
// write our file and sync the times.
fs.writeFileSync(fileName, res.data.access_token);
fs.utimesSync(fileName, new Date(expiryTime), new Date(expiryTime));
// resolve our promise with our generated token.
resolve(res.data.access_token);
} catch (err) {
// ToDo: handle token retrieval failure...
console.log(err);
}
});
// once our promise is resolved, set it against our store.
promise.then(
(token) => context.store.commit('bearerToken/setToken', token),
// ToDo: better handling of errors...
(err) => console.log(err)
);
}
}
这使我可以在服务器级别生成一个不记名令牌并将其缓存,然后我可以将其与 SSR 或客户端一起使用。