Javascript 如何使用基本身份验证?在我的示例中,Auth头可以很好地发送到入口点,但不能发送到所有其他端点

Javascript 如何使用基本身份验证?在我的示例中,Auth头可以很好地发送到入口点,但不能发送到所有其他端点,javascript,reactjs,react-admin,api-platform.com,Javascript,Reactjs,React Admin,Api Platform.com,我有一个在/api下运行的api 它需要基本的Http身份验证(由于本文,JWT不需要)。 因此,我配置了authProvider和fetchHydra来构建头部 此标头会很好地发送到以下3个主要端点: /原料药 /api/docs.jsonld /入口点 但随后,它尝试在不使用基本Http的情况下调用所有资源端点,以便它们都使用Http 401响应 这是我的密码: // admin.js (app main resource) import React from 'react'; imp

我有一个在/api下运行的api 它需要基本的Http身份验证(由于本文,JWT不需要)。 因此,我配置了authProvider和fetchHydra来构建头部

此标头会很好地发送到以下3个主要端点:

  • /原料药
  • /api/docs.jsonld
  • /入口点
但随后,它尝试在不使用基本Http的情况下调用所有资源端点,以便它们都使用Http 401响应

这是我的密码:

// admin.js (app main resource)

import React from 'react';
import parseHydraDocumentation from '@api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation';
import { HydraAdmin, hydraClient, fetchHydra as baseFetchHydra } from '@api-platform/admin';
import ReactDOM from 'react-dom';
import authProvider from './src/authProvider';
import { Route, Redirect } from 'react-router-dom';

const entrypoint = document.getElementById('api-entrypoint').innerText;
// Fetch api route with Http Basic auth instead of JWT Bearer system
const fetchHeaders = {"Authorization": `Basic ${btoa(`${localStorage.getItem('username')}:${localStorage.getItem('token')}`)}`};
// original system with JWT
// const fetchHeaders = {'Authorization': `Bearer ${localStorage.getItem('token')}`};
const fetchHydra = (url, options = {}) => baseFetchHydra(url, {
    ...options,
    headers: new Headers(fetchHeaders),
});
const dataProvider = api => {
    return hydraClient(api, fetchHydra);
}
const apiDocumentationParser = entrypoint =>
    parseHydraDocumentation(entrypoint, {
        headers: new Headers(fetchHeaders),
    }).then(
        ({ api }) => ({ api }),
        result => {
            const { api, status } = result;

            if (status === 401) {
                return Promise.resolve({
                    api,
                    status,
                    customRoutes: [
                        <Route path="/" render={() => <Redirect to="/login" />} />,
                    ],
                });
            }

            return Promise.reject(result);
        }
    );

ReactDOM.render(
    <HydraAdmin
        apiDocumentationParser={apiDocumentationParser}
        authProvider={authProvider}
        entrypoint={entrypoint}
        dataProvider={dataProvider}
    />, document.getElementById('api-platform-admin'));

//admin.js(应用程序主资源)
从“React”导入React;
从“@api platform/api doc parser/lib/hydra/parseHydraDocumentation”导入parseHydraDocumentation;
从'@api platform/admin'导入{hydradmin,hydraClient,fetchHydra as baseFetchHydra};
从“react dom”导入react dom;
从“/src/authProvider”导入authProvider;
从“react router dom”导入{Route,Redirect};
const entrypoint=document.getElementById('api-entrypoint')。innerText;
//使用Http基本身份验证而不是JWT承载系统获取api路由
const fetchHeaders={“Authorization”:`基本${btoa(`${localStorage.getItem('username')}:${localStorage.getItem('token')}})}};
//使用JWT的原始系统
//const fetchHeaders={'Authorization':`Bearer${localStorage.getItem('token')}};
const fetchHydra=(url,options={})=>baseFetchHydra(url{
…选项,
标题:新标题(fetchHeaders),
});
const dataProvider=api=>{
返回hydraClient(api、fetchHydra);
}
const apiDocumentationParser=entrypoint=>
解析文档(入口点{
标题:新标题(fetchHeaders),
}).那么(
({api})=>({api}),
结果=>{
const{api,status}=result;
如果(状态===401){
还愿({
应用程序编程接口,
地位
海关路线:[
} />,
],
});
}
返回承诺。拒绝(结果);
}
);
ReactDOM.render(
,document.getElementById('api-platform-admin');
//admin/src/authProvider.js
从“react admin”导入{AUTH_LOGIN,AUTH_LOGOUT,AUTH_ERROR,AUTH_CHECK};
//将此更改为您自己的身份验证令牌URI。
const authenticationTokenUri=`${document.getElementById('api-entrypoint')。innerText}/login`;
导出默认值(类型、参数)=>{
开关(类型){
案例验证登录:
const{username,password}=params;
常量请求=新请求(authenticationTokenUri{
方法:“POST”,
body:JSON.stringify({username:username,password}),
标题:新标题({'Content Type':'application/json'}),
});
返回获取(请求)
。然后(响应=>{
如果(response.status<200 | | response.status>=300)抛出新错误(response.statusText);
返回response.json();
})
。然后({token})=>{
setItem('username',username);
setItem('token',token);//该标记存储在浏览器的本地存储中
window.location.replace('/');
});
案例验证注销:
localStorage.removietem('username');
localStorage.removietem('token');
打破
案例验证错误:
如果(401==参数状态| | 403==参数状态){
localStorage.removietem('username');
localStorage.removietem('token');
返回承诺。拒绝();
}
打破
案例验证检查:
返回localStorage.getItem('token')?Promise.resolve():Promise.reject();
违约:
返回承诺。解决();
}
}
我的应用程序使用的是PHP Symfony Api平台(2.4.5)和Api平台管理(0.6.3,其中嵌入了react Admin^2.7.0)
我在github上推送了repo:

好的,所以问题与我的代码无关。哦,是的,这不是我的错。 事实上,它与包@api platform/admin的0.6.3版本有关,该版本破坏了身份验证系统。 解决方案是回滚到包的版本0.6.2


多亏了这个线程:

我猜
fetchHeaders
仅在本地存储为空时初始化一次。使它成为一个函数,并为每次获取调用它。@florian。这似乎不是问题,因为我让它在JWT基于官方文档的情况下工作:登录正常后,对entrypoints的前3个调用都正常(因此标题设置良好),而不是下一个调用。即使有一个函数调用,它也只执行一次。不幸的是,这最终也是我的修复方法,我甚至不知道它为什么会坏掉,它根本不起作用。
// admin/src/authProvider.js

import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK } from 'react-admin';

// Change this to be your own authentication token URI.
const authenticationTokenUri = `${document.getElementById('api-entrypoint').innerText}/login`;

export default (type, params) => {
    switch (type) {
        case AUTH_LOGIN:
            const { username, password } = params;
            const request = new Request(authenticationTokenUri, {
                method: 'POST',
                body: JSON.stringify({ username: username, password }),
                headers: new Headers({ 'Content-Type': 'application/json' }),
            });

            return fetch(request)
                .then(response => {
                    if (response.status < 200 || response.status >= 300) throw new Error(response.statusText);

                    return response.json();
                })
                .then(({ token }) => {
                    localStorage.setItem('username', username);
                    localStorage.setItem('token', token); // The token is stored in the browser's local storage
                    window.location.replace('/');
                });

        case AUTH_LOGOUT:
            localStorage.removeItem('username');
            localStorage.removeItem('token');
            break;

        case AUTH_ERROR:
            if (401 === params.status || 403 === params.status) {
                localStorage.removeItem('username');
                localStorage.removeItem('token');

                return Promise.reject();
            }
            break;

        case AUTH_CHECK:
            return localStorage.getItem('token') ? Promise.resolve() : Promise.reject();

        default:
            return Promise.resolve();
    }
}