Я развертываю свой сервер Node.js на AKS, и у меня возникает несколько непредвиденных ситуаций, которые не происходят на моем локальном компьютере. Я пробовал разные вещи, чтобы отладить его, но у меня ничего не получается.
Я использую промежуточное ПО как
exports.clientApiKeyValidation = (req, res, next) => {
try {
const clientApiKey = req.get('api_key');
console.info(`received api_key is ${clientApiKey}
and expected API_KEY is ${process.env.API_KEY}`);
const receivedTypeof = console.info('clientApiKey ', typeof clientApiKey);
const expectedTypeof = console.info('expected ', typeof process.env.API_KEY);
console.info('req.headers is: ', req.headers);
if (!clientApiKey) {
return res.status(400).send({
status: false,
message: "Missing Api Key"
});
}
if (clientApiKey === process.env.API_KEY) {
// console.info('Api key correct');
next();
}
else {
return res.status(400).send({
status: false,
message: "Invalid Api Key"
});
}
} catch (error) {
res.status(401).json({
error: new Error('Invalid request!')
});
}
}
используется на таких маршрутах, как
router.get('/users', auth.clientApiKeyValidation, userController.findUsers);
В app.js
я также установил несколько вещей, в том числе функцию промежуточного программного обеспечения, позволяющую использовать эти параметры как
app.disable('x-powered-by');
app.use(express.json({ limit: '50mb' }));
app.use(function (req, res, next) {
// either res.setHeader or res.header works.
// res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
res.setHeader(
'Access-Control-Allow-Origin',
'https://xxx.westeurope.cloudapp.azure.com'
);
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE'
);
// res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader(
'Access-Control-Allow-Headers',
'content-type, api_key, AuthToken, apikey'
);
// res.setHeader('Access-Control-Allow-Credentials', true);
// res.header('Access-Control-Allow-Origin', 'http://localhost:5000');
// res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, api_key, Accept');
// console.info(' res headers added: ', res.getHeaders());
next();
});
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(express.json());
app.use(express.json({ type: 'application/json' }));
Я отправляю ему запросы из своего приложения Flutter, добавляя заголовки, например
await _firebaseAuth.currentUser?.getIdToken().then((idToken) {
headers = {
'Content-Type': 'application/json',
'api_key': Environment.dbApiKey,
'AuthToken': idToken
};
});
FixitUser? userDetails;
// final Uri uri = Uri.http(Environment.dbUrl, '/api/users');
final Uri uri = Uri.https(Environment.dbUrl, '/server/api/users');
log('headers are $headers');
await get(uri, headers: headers).then((resp) {
log('UserMongoDBRepository.downloadUserDetails resp.body is : ${resp.body}');
...
При запуске сервера напрямую журналы промежуточного программного обеспечения показывают, что все работает так, как ожидалось.
received api_key is hjkdiu-slia7h-si9udd989jw-ols8dh
and expected API_KEY is hjkdiu-slia7h-si9udd989jw-ols8dh
clientApiKey string
expected string
req.headers is: {
'user-agent': 'Dart/2.18 (dart:io)',
'accept-encoding': 'gzip',
api_key: 'hjkdiu-slia7h-si9udd989jw-ols8dh',
host: '192.168.1.48:3000',
'content-type': 'application/json',
authtoken: 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjVhNTA5ZjAxOWY3MGQ3NzlkODBmMTUyZDFhNWQzMzgxMWFiN2NlZjciLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoidmluY2Vuem8gY2FsaWEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDYuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy13TVNwMUxZd2hPZy9BQUFBQUFBQUFBSS9BQUFBQUFBQUFCSS9OdE43TTlTMEVIUS9zOTYtYy9waG90by5qcGciLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZml4LWl0LWI0YjAwIiwiYXVkIjoiZml4LWl0LWI0YjAwIiwiYXV0aF90aW1lIjoxNjc1Nzc1MTg2LCJ1c2VyX2lkIjoiWnhtejJHSmxNUlBXdjBMRGgyRDg4Y0o3T3V6MSIsInN1YiI6Ilp4bXoyR0psTVJQV3YwTERoMkQ4OGNKN091ejEiLCJpYXQiOjE2NzU4NDY4MDAsImV4cCI6MTY3NTg1MDQwMCwiZW1haWwiOiJ2aW5jZW56by5jYWxpYS4xOTc2QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwaG9uZV9udW1iZXIiOiIrMzkzNjYxNDcxMzEzIiwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNjkyMTg2MTcwOTA0NTM5MzU5MiJdLCJwaG9uZSI6WyIrMzkzNjYxNDcxMzEzIl0sImVtYWlsIjpbInZpbmNlbnpvLmNhbGlhLjE5NzZAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiZ29vZ2xlLmNvbSJ9fQ.ZNJFrxWlycMVgg4VAdWt6Q0WR5yrWPar5_UJwhQ9-hVX25aKC69yDpoM2adx3OIQ-hlsGz1bNvVEUSfvWUWRWF-TaX2TVeLb5z0blAtl8A1cGcvnaryffr0jpCtN_nhDg3WTtHw4B2USDe432TxSXx0ICrk8bx_fum8jsfBvAh_xU8bnr6lLsc0pltcmU-zun0rhZcC6jpxua2d0jIwWyWSXurjNBkLkduzOpUbw6KCLur7wVcxz-HmuD67D0qx5dr37malLbOBt5mcfOtdJEJcEq55XqXqUanopT_OWTWxByMrD_CXyZnLu_q1DgSBMM4kaLrSA14ETD_EvIeqHOQ',
}
Когда вместо этого он работает в кластере AKS, api_key
отсутствует в заголовках полученных запросов, как показывают журналы, поэтому промежуточное ПО отвечает {"status":false,"message":"Missing Api Key"}
received api_key is undefined
and expected API_KEY is some api key
req.headers is: {
host: 'xxx.westeurope.cloudapp.azure.com',
'x-request-id': '2ecc2ec74c808cf40f816921374f72d4',
'x-real-ip': '81.56.11.23',
'x-forwarded-for': '81.56.11.23',
'x-forwarded-host': 'xxx.westeurope.cloudapp.azure.com',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https',
'x-forwarded-scheme': 'https',
'x-scheme': 'https',
'user-agent': 'Dart/2.18 (dart:io)',
'accept-encoding': 'gzip',
'content-type': 'application/json',
authtoken: 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjVhNTA5ZjAxOWY3MGQ3NzlkODBmMTUyZDFhNWQzMzgxMWFiN2NlZjciLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoidmluY2Vuem8gY2FsaWEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDYuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy13TVNwMUxZd2hPZy9BQUFBQUFBQUFBSS9BQUFBQUFBQUFCSS9OdE43TTlTMEVIUS9zOTYtYy9waG90by5qcGciLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZml4LWl0LWI0YjAwIiwiYXVkIjoiZml4LWl0LWI0YjAwIiwiYXV0aF90aW1lIjoxNjcxODc0Nzg2LCJ1c2VyX2lkIjoiWnhtejJHSmxNUlBXdjBMRGgyRDg4Y0o3T3V6MSIsInN1YiI6Ilp4bXoyR0psTVJQV3YwTERoMkQ4OGNKN091ejEiLCJpYXQiOjE2NzU3NjkyNzksImV4cCI6MTY3NTc3Mjg3OSwiZW1haWwiOiJ2aW5jZW56by5jYWxpYS4xOTc2QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwaG9uZV9udW1iZXIiOiIrMzkzNjYxNDcxMzEzIiwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNjkyMTg2MTcwOTA0NTM5MzU5MiJdLCJwaG9uZSI6WyIrMzkzNjYxNDcxMzEzIl0sImVtYWlsIjpbInZpbmNlbnpvLmNhbGlhLjE5NzZAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiZ29vZ2xlLmNvbSJ9fQ.d8emU2BKNBV5oe3YQVHT8M8otFos_RvEmeyutdmYBDhnzyPgMZTAn_l3JikRAbcTNdDOAVoutZgTb5s8d6di3plAoE240OwwZTuSwxVpSaS7fDPt_rjQf9k2RmVsRa-fq1SWIP2ejdEbma_QngLSpXO0-PSPx4wa7mThjv2enP00TpUB9RDsOPK2QKlwOX9i1gc1_7kOPGJwouG3S3W4_kOXIxSoVjAT0P9k2xtHa99W-_gwn-9YqM1UoHrLkEs-ONKpe5SWLIet9r_PvI2l1zqb-1fGBmoeBhyzSijw_cOLJSayEoImtkCOmAA0rhMNYc--Yxuzd8EMyyp1U9dThg'
}
Печать заголовков из Flutter показывает, что ключ api_key установлен правильно.
headers are {Content-Type: application/json, api_key: some api key, AuthToken: eyJhbGciOiJSUzI1NiIsImtpZCI6IjVhNTA5ZjAxOWY3MGQ3NzlkODBmMTUyZDFhNWQzMzgxMWFiN2NlZjciLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoidmluY2Vuem8gY2FsaWEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDYuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy13TVNwMUxZd2hPZy9BQUFBQUFBQUFBSS9BQUFBQUFBQUFCSS9OdE43TTlTMEVIUS9zOTYtYy9waG90by5qcGciLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZml4LWl0LWI0YjAwIiwiYXVkIjoiZml4LWl0LWI0YjAwIiwiYXV0aF90aW1lIjoxNjcxODc0Nzg2LCJ1c2VyX2lkIjoiWnhtejJHSmxNUlBXdjBMRGgyRDg4Y0o3T3V6MSIsInN1YiI6Ilp4bXoyR0psTVJQV3YwTERoMkQ4OGNKN091ejEiLCJpYXQiOjE2NzU3NjkyNzksImV4cCI6MTY3NTc3Mjg3OSwiZW1haWwiOiJ2aW5jZW56by5jYWxpYS4xOTc2QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwaG9uZV9udW1iZXIiOiIrMzkzNjYxNDcxMzEzIiwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNjkyMTg2MTcwOTA0NTM5MzU5MiJdLCJwaG9uZSI6WyIrMzkzNjYxNDcxMzEzIl0sImVtYWlsIjpbInZpbmNlbnpvLmNhbGlhLjE5NzZAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiZ29vZ2xlLmNvbSJ9fQ.d8emU2BKNBV5oe3YQVHT8M8otFos_RvEmeyutdmYBDhnzyPgMZTAn_l3JikRAbcTNdDOAVoutZgTb5s8d6di3plAoE240OwwZTuSwxVpSaS7fDPt_rjQf9k2RmVsRa-fq1SWIP2ejdEbma_QngLSpXO0-PSPx4wa7mThjv2enP00TpUB9RDsOPK2QKlwOX9i1gc1_7kOPGJwouG3S3W4_kOXIxSoVjAT0P9k2xtHa99W-_gwn-9YqM1UoHrLkEs-ONKpe5SWLIet9r_PvI2l1zqb-1fGBmoeBhyzSijw_cOLJSayEoImtkCOmAA0rhMNYc--Yxuzd8EMyyp1U9dThg}
Итак, в качестве теста вместо api_key
я использовал apikey
, и он извлекается в запросе, но затем проверка ===
завершается неудачно, поэтому промежуточное ПО отвечает {"status":false,"message":"Invalid Api Key"}
, даже если их тип и значение идентичны, как проверено здесь https://developer. mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality
received api_key is hjkdiu-slia7h-si9udd989jw-ols8dh
and expected API_KEY is hjkdiu-slia7h-si9udd989jw-ols8dh
clientApiKey string
expected string
req.headers is: {
host: 'fixit1.westeurope.cloudapp.azure.com',
'x-request-id': '515ad2a00b1a3db24a69e09f6d181036',
'x-real-ip': '81.56.11.23',
'x-forwarded-for': '81.56.11.23',
'x-forwarded-host': 'fixit1.westeurope.cloudapp.azure.com',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https',
'x-forwarded-scheme': 'https',
'x-scheme': 'https',
'user-agent': 'Dart/2.18 (dart:io)',
'accept-encoding': 'gzip',
'content-type': 'application/json',
authtoken: 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjVhNTA5ZjAxOWY3MGQ3NzlkODBmMTUyZDFhNWQzMzgxMWFiN2NlZjciLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoidmluY2Vuem8gY2FsaWEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDYuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy13TVNwMUxZd2hPZy9BQUFBQUFBQUFBSS9BQUFBQUFBQUFCSS9OdE43TTlTMEVIUS9zOTYtYy9waG90by5qcGciLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZml4LWl0LWI0YjAwIiwiYXVkIjoiZml4LWl0LWI0YjAwIiwiYXV0aF90aW1lIjoxNjc1Nzc1MTg2LCJ1c2VyX2lkIjoiWnhtejJHSmxNUlBXdjBMRGgyRDg4Y0o3T3V6MSIsInN1YiI6Ilp4bXoyR0psTVJQV3YwTERoMkQ4OGNKN091ejEiLCJpYXQiOjE2NzU4NDMxNzgsImV4cCI6MTY3NTg0Njc3OCwiZW1haWwiOiJ2aW5jZW56by5jYWxpYS4xOTc2QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwaG9uZV9udW1iZXIiOiIrMzkzNjYxNDcxMzEzIiwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNjkyMTg2MTcwOTA0NTM5MzU5MiJdLCJwaG9uZSI6WyIrMzkzNjYxNDcxMzEzIl0sImVtYWlsIjpbInZpbmNlbnpvLmNhbGlhLjE5NzZAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiZ29vZ2xlLmNvbSJ9fQ.lDMgmTJkrm6ZnoyEU1F7Sjoo7Y8or8ZKzIrwBJ9ssQiR8yN5KD2ZhyM6yyR_Arscmyg1ZV_6RsTnFgGsVsmjiMzyX6TOXmYkmRlvvMjjjFsV8rW_W_gIdVld6vSg-JMrOlLcCeBknFDJC50bbNGYBSwQ2_C_MZIKlbFWWrqME988MOiUBlyT86t5Oofc5uVMETrpBf0a-wsFRdyEX-3uj-T3MRHza62PTcpHURoptQdIzYsBSc6WxR6WCINVjx__DbWlWrGt612Mw4iLv1XReiGriQEjTDc9cXbG0ngbiRsn0ojvZ-Jb8Pb6kj7gWRYDRsKFg2nxxFMhVeSDuIeO-w',
apikey: 'hjkdiu-slia7h-si9udd989jw-ols8dh'
}
В качестве второго теста я изменил оператор ===
на ==
в промежуточном программном обеспечении, но он все равно возвращает false и отвечает {"status":false,"message":"Invalid Api Key"}
.
Затем я попытался использовать const serverApiKey = JSON.stringify(process.env.API_KEY);
и const clientApiKey = JSON.stringify(req.get('apikey'));
для сравнения, и они действительно дают разные результаты.
clientApiKey json string is: "hjkdiu-slia7h-si9udd989jw-ols8dh"
serverApiKey json string is: "hjkdiu-slia7h-si9udd989jw-ols8dh\n"
env.API_KEY
действительно получает значение из секрета k8s, base64, закодированного с помощью команды echo -n hjkdiu-slia7h-si9udd989jw-ols8dh |base64
. Чтобы увидеть, было ли это пустым местом в закодированном значении из секрета, я попытался закодировать его с флагом -n
и без него, но они приводят к одной и той же закодированной строке json.
Я не уверен, что это может иметь какое-то отношение к образу докера, который я создаю, поэтому вот Dockrfile
FROM node:18.3.0
WORKDIR /usr/app
# where available (npm@5+)
COPY ./ package.json ./
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
# Istall the dependencies
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
COPY ./ ./
# Add the following lines for create-react-app bug, workaround
ENV CI=true
ENV WDS_SOCKET_PORT=0
CMD ["npm", "start"]
api_key
param отсутствует, а apikey
param есть в заголовках полученных запросов?\n
в serverApiKey
, а не в clientApiKey
?Большое спасибо, как всегда.
@robertklep Большое спасибо. Действительно кажется, что это была первая проблема, но ее легко решить. Теперь проблема заключается в том, что ключ API, который я отправляю от клиента, не соответствует ключу API сервера, исходя из закодированного в base64 значения в секрете сервера, поэтому промежуточное ПО отвечает сообщением wrong key
. Я обновил тело вопроса, чтобы показать свои тесты. Любое предложение по этому поводу? я хожу кругами
Я ничего не знаю об AKS, но я бы, наверное, просто списал это на платформу и использовал process.env.API_KEY.trim()
(или .trimEnd()
)
да, я тоже не уверен в причине этого, но /n заставил меня задуматься о добавленных пробелах. Я пробовал .trim(), и это было! Большое спасибо. Не могли бы вы превратить это в ответ, чтобы я мог его принять?
Я ничего не знаю об AKS, но некоторые реализации HTTP-серверов (например, nginx) не принимают символы подчеркивания в именах заголовков HTTP.
Что касается того, почему ключи API сервера содержат завершающую новую строку: это может быть связано с платформой. Я бы просто прагматично отнесся к этому и удалил его перед использованием: process.API_KEY.trim()
Большое спасибо еще раз. Я буду использовать .trim()
повсюду. Я принимаю здесь политику нулевого доверия, лол.
Некоторые реализации HTTP-сервера не принимают символы подчеркивания в именах заголовков HTTP.