#asp.net #reactjs #azure #azure-web-app-service #create-react-app
Вопрос:
Попытка опубликовать значение по умолчанию ASP.NET Ядро с приложением React, но с идентификацией. Вот клиентское приложение MS readme
Похоже, это работает без идентификации, публикуясь непосредственно из visual studio.
Но как только личность будет добавлена, это станет сложнее. С помощью identity у нас есть дополнительная wwwroot
папка на этапе публикации.
вот код приложения, которое я тестирую. Вот информация MS, которую я использовал для идентификации и аутентификации. Это приложение входит в систему локально, и в моих пользовательских секретах я настроил
{
"Authentication:Microsoft:ClientId": "IdValue",
"Authentication:Microsoft:ClientSecret": "SecrectValue"
}
После публикации он будет выброшен Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
в консоль. Но опять же, не по местному.
Структура папок публикации без идентификации
wwwroot
├── ClinetApp
├── build
├── static
├── css
└── js
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.<guid>.js
└──service-worker.js
├── appsetting.json
├── appsetting.Development.json
├── MS-DLLs
├── App.dll
├── App.exe
├── App.pdb
├── App.deps.json
├── App.runtimeconfig.json
├── App.Views.dll
├── App.Views.pdb
└── web.config //default web config
Для развертывания в azure с помощью этого сообщения в блоге (из ClinetApp/ReadMe
) необходимо добавить еще одну веб wwwroot
-конфигурацию в дополнение к перемещению ClinetApp/build
папки wwwroot
. Очень похоже на обычное asp.net основное приложение все статические ресурсы затем помещаются в wwwroot
папку, а библиотека dll перемещается в родительскую папку.
Развертывание без использования второй веб — конфигурации приводит к этим ошибкам слева. Ошибки справа появляются после добавления второй веб-конфигурации в проект идентификации.
Веб-конфигурация для проекта идентификации, исправляющая две ошибки консоли
<?xml version="1.0"?>
<configuration>
<system.webServer>
<!--This section is for manifest.json not found error -->
<staticContent>
<mimeMap fileExtension=".woff2" mimeType="application/x-font-woff" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<rewrite>
<rules>
<!--This section is for "could not load setting for "App" in AuthorizeService.js" error -->
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/ (api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Структура папок публикации с идентификатором
├── wwwroot
├── static
├── css
└── js
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.<guid>.js
├── //service-worker.js is not used with idenity, see index.html code for explination
└── web.config //used for the routing from blog post
├── appsetting.json
├── appsetting.Development.json
├── MS-DLLs
├── App.dll
├── App.exe
├── App.pdb
├── App.deps.json
├── App.runtimeconfig.json
├── App.Views.dll
├── App.Views.pdb
└── web.config //default web config
Once those issues are fixed from the web config it seems that index.html isn’t read correctly. every page request gets Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
when serving the index.html. This is using react-router
so one of the suggested fixes was
-app.get('/', function (req, res) {
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
but since this is using react router we aren’t calling this code in the solution. Below are the App.js
, index.js
, and index.html
index.js
import 'bootstrap/dist/css/bootstrap.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
//import registerServiceWorker from './registerServiceWorker';
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');
ReactDOM.render(
<Router basename={baseUrl}>
<App />
</Router>,
rootElement);
// Uncomment the line above that imports the registerServiceWorker function
// and the line below to register the generated service worker.
// By default create-react-app includes a service worker to improve the
// performance of the application by caching static assets. This service
// worker can interfere with the Identity UI, so it is
// disabled by default when Identity is being used.
//
//registerServiceWorker();
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<base href="%PUBLIC_URL%/" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>CPTest</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
App.js
import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';
import AuthorizeRoute from './components/api-authorization/AuthorizeRoute';
import ApiAuthorizationRoutes from './components/api-authorization/ApiAuthorizationRoutes';
import { ApplicationPaths } from './components/api-authorization/ApiAuthorizationConstants';
import './custom.css'
export default class App extends Component {
static displayName = App.name;
render () {
return (
<Layout>
<Route exact path='/' component={Home} />
<Route path='/counter' component={Counter} />
<AuthorizeRoute path='/fetch-data' component={FetchData} />
<Route path={ApplicationPaths.ApiAuthorizationPrefix} component={ApiAuthorizationRoutes} />
</Layout>
);
}
}
В Startup.cs
них, похоже, также нарушается тот, у которого нет личности, при попытке добавить личность в проект.
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
Ошибка инструментов разработки для index.html не будучи json
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
Так что дело в том, что я заметил.
- Кажется, все работает в wwwroot, если не используется идентификатор
- После того, как файлы удостоверений необходимо переместить, в wwwroot и во второй веб-конфигурации будут только статические
- Все еще кажется, что это не работает, потому что он ожидает json, но получает index.html
- Страница входа в систему на самом деле является страницей cshtml. На локальном хосте react-маршрутизатор перенаправляет на эту страницу.
_LoginPartial.cshtml
Публикация (слева) против локального хоста (справа) для страницы входа в систему
Опубликовать (слева) против локального хоста (справа) для страницы счетчика (только реагировать)
Я также выполнил эти шаги для развертывания в prod.
С идентификацией это становится немного странным, без нее все работает в службе приложений azure прямо с шага публикации. Не знаете, какую конфигурацию нужно изменить или кто-нибудь решил эту проблему другим способом? Или если что-то с маршрутизатором react нужно изменить? Есть какие-нибудь предложения?
Ответ №1:
У меня была одна и та же проблема как на сервере prem, так и в Azure. Мне пришлось установить SSL-сертификат, на локальном хосте используется сертификат разработчика, как только вы переместите его на рабочий сервер, вам понадобится сертификат SSL для работы сервера идентификации. Кроме того, вы можете переместить DevCert на рабочий сервер ТОЛЬКО в целях тестирования (я сделал это для on-prem, не уверен, что для Azure). Я не помню, как это сделать сразу. Я думаю, что я экспортировал файл .pex или .cer. Я просто не могу сейчас найти свои заметки. Быстрый поиск должен помочь.
Вам нужно будет изменить свой файл appsetting.json следующим образом (посмотрите в разделе «Ключ»), если вы решили использовать сертификат разработки localhost
"IdentityServer": {
"Clients": {
"AdminPortal": {
"Profile": "IdentityServerSPA"
}
},
"Key": {
"Type": "Store",
"StoreName": "MY",
"StoreLocation": "LocalMachine",
"Name": "CN=localhost"
}
},
Комментарии:
1. Я попытался использовать это как исправление. Добавил его, и я все еще получаю сообщение об ошибке
index.html
. Возможно, кому-то понадобится это исправление, потому что я также пропустил этот шаг при переходе на службу приложений от разработчика. Хороший улов2. Кроме того, см. Ответ cameronjchurch об отключении ServiceWorker, поскольку в нем четко упоминается, что у ServiceWorker есть проблемы с odic-клиентом ID4, если вы использовали шаблон проекта React по умолчанию из VS 2019 с идентификатором
Ответ №2:
У меня была та же проблема с парой решений, над которыми я работал в свободное время. Наконец-то нашел решение, которое решило эту проблему на данный момент. Взял идею из этой ссылки. https://github.com/facebook/create-react-app/issues/1910
Проблема для меня заключалась в том, что сотрудник службы перехватывал запрос на аутентификацию и вместо перенаправления на соответствующую страницу (вход или регистрация) просто возвращал 200.
В итоге я отключил работника службы, используя следующее в своем index.html страница.
import 'bootstrap/dist/css/bootstrap.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
//import registerServiceWorker from './registerServiceWorker';
import { unregister } from './registerServiceWorker.js';
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');
unregister();
ReactDOM.render(
<BrowserRouter basename={baseUrl}>
<App />
</BrowserRouter>,
rootElement);
С помощью этого вы можете удалить материал для перезаписи веб-конфигурации. Он не идеален в том смысле, что отключает повышение производительности с помощью сотрудника службы, но он поможет вам решить проблему, связанную с невозможностью перехода на страницу входа в Azure.