如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序
Posted
技术标签:
【中文标题】如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序【英文标题】:How to integrate azure ad into a react web app that consumes a REST API in azure too 【发布时间】:2018-10-22 15:40:05 【问题描述】:我有一个 Web 应用程序,它是 React,并且我已经为 Web 应用程序本身配置了 Azure AD 身份验证。它的 100% 客户端站点应用程序,没有服务器端组件。
我使用了这个组件: https://github.com/salvoravida/react-adal
我的代码如下: adalconfig.js
import AuthenticationContext, adalFetch, withAdalLogin from 'react-adal';
export const adalConfig =
tenant: 'mytenantguid',
clientId: 'myappguid',
endpoints:
api: '14d71d65-f596-4eae-be30-27f079bf8d4b',
,
cacheLocation: 'localStorage',
;
export const authContext = new AuthenticationContext(adalConfig);
export const adalApiFetch = (fetch, url, options) =>
adalFetch(authContext, adalConfig.endpoints.api, fetch, url, options);
export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints.api);
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import DashApp from './dashApp';
import registerServiceWorker from './registerServiceWorker';
import 'antd/dist/antd.css';
import runWithAdal from 'react-adal';
import authContext from './adalConfig';
const DO_NOT_LOGIN = false;
runWithAdal(authContext, () =>
ReactDOM.render(<DashApp />, document.getElementById('root'));
// Hot Module Replacement API
if (module.hot)
module.hot.accept('./dashApp.js', () =>
const NextApp = require('./dashApp').default;
ReactDOM.render(<NextApp />, document.getElementById('root'));
);
,DO_NOT_LOGIN);
registerServiceWorker();
dashapp.js
import React from "react";
import Provider from "react-redux";
import store, history from "./redux/store";
import PublicRoutes from "./router";
import ThemeProvider from "styled-components";
import LocaleProvider from "antd";
import IntlProvider from "react-intl";
import themes from "./settings/themes";
import AppLocale from "./languageProvider";
import config,
getCurrentLanguage
from "./containers/LanguageSwitcher/config";
import themeConfig from "./settings";
import DashAppHolder from "./dashAppStyle";
import Boot from "./redux/boot";
const currentAppLocale =
AppLocale[getCurrentLanguage(config.defaultLanguage || "english").locale];
const DashApp = () => (
<LocaleProvider locale=currentAppLocale.antd>
<IntlProvider
locale=currentAppLocale.locale
messages=currentAppLocale.messages
>
<ThemeProvider theme=themes[themeConfig.theme]>
<DashAppHolder>
<Provider store=store>
<PublicRoutes history=history />
</Provider>
</DashAppHolder>
</ThemeProvider>
</IntlProvider>
</LocaleProvider>
);
Boot()
.then(() => DashApp())
.catch(error => console.error(error));
export default DashApp;
export AppLocale ;
直到此时一切正常,当用户未通过身份验证时,它会重定向到 login.live.com 进行身份验证,然后将其重定向回来。
不过,我还创建了另一个用于托管 REST API 的 azure webapp,该 REST API 已在 Azure AD 中配置,因此尝试使用其余 API 的用户需要经过身份验证。
现在的问题是:如何设置我的客户端 APP 以使用受 Azure AD 保护的 REST API。?
我找到了这个,看起来我在找什么,但我不确定如何将它集成到我上面的现有代码中
https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/481
更新: 对于潜在的读者
这个答案加上这个 url 上配置应用注册的说明帮助我解决了这个问题:https://blog.ithinksharepoint.com/2016/05/16/dev-diary-s01e06-azure-mvc-web-api-angular-and-adal-js-and-401s/
【问题讨论】:
检查这可能会帮助你azure.microsoft.com/en-in/resources/videos/… 【参考方案1】:这里的关键是adalApiFetch
,定义在adalConfig.js
中。如您所见,它是adalFetch
的简单包装器。这个方法(在react-adal
中定义)接收一个ADAL实例(authContext
)、一个资源标识符(resourceGuiId
)、一个方法(fetch
)、一个URL(url
)和一个对象(options
) )。该方法执行以下操作:
-
使用 ADAL 实例 (
authContext
) 获取由 resourceGuiId
标识的资源的访问令牌。
将此访问令牌添加到options
对象的headers
字段(如果未提供,则创建一个)。
调用给定的“fetch”方法,传入url
和options
对象作为参数。
adalApiFetch
方法(您已在 adalConfig.js
中定义)只需使用在 adalConfig.endpoints.api
中标识的资源调用 adalFetch
。
好的,那么您如何使用所有这些来发出 REST 请求,并在您的 React 应用程序中使用响应?让我们举个例子。在以下示例中,我们将使用 Microsoft Graph API 作为受 Azure AD 保护的 REST API。我们将通过它的友好标识符 URI(“https://graph.microsoft.com”)来识别它,但请记住,它也可以是 Guid 应用 ID。
adalConfig.js 定义 ADAL 配置,并导出几个辅助方法:
import AuthenticationContext, adalFetch, withAdalLogin from 'react-adal';
export const adalConfig =
tenant: 'tenant-id-or-domain-name',
clientId: 'app-id-of-native-client-app',
endpoints:
api: 'https://graph.microsoft.com' // <-- The Azure AD-protected API
,
cacheLocation: 'localStorage',
;
export const authContext = new AuthenticationContext(adalConfig);
export const adalApiFetch = (fetch, url, options) =>
adalFetch(authContext, adalConfig.endpoints.api, fetch, url, options);
export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints.api);
index.js 使用来自react-adal
的runWithAdal
方法包装indexApp.js
,确保用户在加载indexApp.js
之前使用Azure AD 进行签名:
import runWithAdal from 'react-adal';
import authContext from './adalConfig';
const DO_NOT_LOGIN = false;
runWithAdal(authContext, () =>
// eslint-disable-next-line
require('./indexApp.js');
,DO_NOT_LOGIN);
indexApp.js 只是加载和渲染App
的一个实例,这里没什么特别的:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
App.js 是一个神奇的简单组件:
我们定义了一个state
值。在本例中,它被称为 apiResponse
,因为我们只是显示原始 API 响应,但当然您可以随意命名此状态(或具有多个状态值)。
在componentDidMount
(在元素在DOM 中可用之后运行)期间,我们调用adalApiFetch
。我们传入fetch
(来自Fetch API 作为fetch
参数,以及我们要发出的REST 请求的端点(在本例中为Microsoft Graph 中的/me
端点):
在render
方法中,我们只是在<pre>
元素中显示此状态值。
import React, Component from 'react';
import adalApiFetch from './adalConfig';
class App extends Component
state =
apiResponse: ''
;
componentDidMount()
// We're using Fetch as the method to be called, and the /me endpoint
// from Microsoft Graph as the REST API request to make.
adalApiFetch(fetch, 'https://graph.microsoft.com/v1.0/me', )
.then((response) =>
// This is where you deal with your API response. In this case, we
// interpret the response as JSON, and then call `setState` with the
// pretty-printed JSON-stringified object.
response.json()
.then((responseJson) =>
this.setState( apiResponse: JSON.stringify(responseJson, null, 2) )
);
)
.catch((error) =>
// Don't forget to handle errors!
console.error(error);
)
render()
return (
<div>
<p>API response:</p>
<pre> this.state.apiResponse </pre>
</div>
);
export default App;
【讨论】:
我收到此错误 Unhandled Rejection (SyntaxError): Unexpected token 我无法评论我看不到的代码。可以分享一下出错的代码吗? 哦,实际上,我可以看到足够多的错误来猜测问题所在。您的 API (/values
) 是否返回 JSON? response.json()
假设它是,并试图反序列化它,但找到一个 <
字符。也许/values
正在返回 html 或 XML?
是的,这也是我的想法,我只是将格式化程序更改为 json 而不是 xml,测试 react 应用程序
这是问题所在,非常感谢,经过 1 周的努力,终于可以正常工作了。【参考方案2】:
上面给出的配置仍然存在问题。我在上面添加了更多配置并且它有效。希望对您有所帮助。
import AuthenticationContext, adalFetch, withAdalLogin from 'react-adal';
export const adalConfig =
tenant: 'tenant-id-or-domain-name',
clientId: 'app-id-of-native-client-app',
endpoints:
api: 'https://graph.microsoft.com'
,
cacheLocation: 'localStorage',
extraQueryParameter: 'prompt=admin_consent'
;
export const authContext = new AuthenticationContext(adalConfig);
【讨论】:
【参考方案3】:Phillipe 的回复让我走上了正确的道路,但我仍然遇到我的令牌不被接受的问题。
aadsTS700051:没有为应用启用 response_type 'token'。
要解决这个问题,我需要进入我的应用注册 > manifest 并将 oauth2AllowImplicitFlow 设置为 true:
"oauth2AllowImplicitFlow": true,
退出您的 Azure 帐户,重新登录,您应该会收到用户的详细信息。
【讨论】:
以上是关于如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
如何将标签添加到在 Microsoft Azure 中创建的文件存储、队列存储和表存储
如何将 Azure Policy 与 Azure DevOps 集成?
正在修改或添加应用程序设置到在 linux 容器上运行的 azure 应用程序服务将回收站点