Я написал бэкенд Spring Boot и интерфейс Angular 8, которые я упаковываю вместе. Поэтому при развертывании оба используют один и тот же порт, и это прекрасно работает.
Во время разработки я хочу, чтобы оба приложения работали отдельно, и настроил это следующим образом:
application.yml
server:
port: 10000
servlet:
context-path: /
DataRestController.java
@RestController
@RequestMapping("/api/data")
public class DataRestController {
@GetMapping()
public Collection<Data> findAll() {
// populate result
return result;
}
}
data.service.ts
export class DataService {
private url = '/api/data';
constructor(private http: HttpClient) {
}
getData(): Observable<Data[]> {
return this.http.get<Data[]>(this.url);
}
}
Чтобы внешний интерфейс мог подключаться к внутреннему, у меня есть следующая команда, определенная в моем файле package.json
:
"start": "ng serve --proxy-config proxy.conf.json --hmr --port 4201"
proxy.conf.json
{
"/api": {
"target": "http://localhost:10000",
"secure": "false"
}
}
Это все работает отлично. Я могу указать браузеру http://localhost:10000/api/data
и получить данные в формате JSON. Запрос внешнего интерфейса к http://localhost:4201/api/data
прозрачно перенаправляется на внутренний URL-адрес, и мое угловое приложение получает его данные.
Однако сейчас мне захотелось перейти на безопасное общение по https. Я предпринял следующие шаги:
Я создал файл PKCS12 с парой ключей, а затем извлек из него закрытый ключ и сертификат:
keytool -genkeypair -alias data -keyalg RSA -keysize 2048 -storetype PKCS12 -validity 3650 -keystore data.p12 -storepass <password>
openssl pkcs12 -info -in data.p12 -nodes -nocerts > data.key
openssl pkcs12 -info -in data.p12 -nokeys > data.cert
Я скопировал файл PKCS12 в /src/main/resources/keystore/data.p12
моего бэкенда, а два других файла в /ssl/data.*
моего внешнего интерфейса.
Я добавил следующие строки в свой файл *application.yml.
server:
ssl:
key-store-type: pkcs12
key-store: classpath:keystore/data.p12
key-alias: data
key-store-password: ENC(<jasypt encrypted password>)
key-password: ENC(<jasypt encrypted password>)
Я также добавил файл SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest()
.requiresSecure()
;
}
}
Если я сейчас запущу свое серверное приложение, оно больше не будет отвечать на URL-адрес http
, но ответит на https://localhost:10000/api/data
(мне пришлось указать firefox принять самозаверяющий сертификат в первый раз, когда я попробовал это, но потом он работает безупречно).
Вот тут-то и начались мои проблемы, когда я попытался подключить свой интерфейс к серверу через https :-(
Я добавил следующий скрипт в package.json.
"start-ssl": "ng serve --proxy-config proxy-secure.conf.json --hmr --port 4201 --ssl true --ssl-cert ssl/data.cert --ssl-key ssl/data.key",
и создал новый файл proxy-secure.conf.json.
{
"/api": {
"target": "https://localhost:10000",
"secure": "true"
},
}
Когда я запускаю start-ssl
, мое приложение теперь обслуживается https://localhost:4201
и нормально загружается в браузере. Однако, когда угловое приложение хочет получить доступ к https://localhost:4201/api/data
, я получаю следующую ошибку в консоли, и браузер показывает, что для запроса возвращается статус HTTP 500.
[HPM] Error occurred while trying to proxy request /api/data from localhost:4201 to localhost (DEPTH_ZERO_SELF_SIGNED_CERT) (https://nodejs.org/api/errors.html#errors_common_system_errors)
Погуглив, я наткнулся на эту беседу на github и последовал различным советам там я попробовал следующее:
{
"/api": {
"target": "https://localhost:10000",
"secure": "false"
},
}
также как и
{
"/api": {
"target": "https://localhost:10000",
"secure": "false"
"changeOrigin": true,
},
}
и я также изменил расширение файла, так что файл теперь proxy-secure.conf.js
var fs = require('fs');
var PROXY_CONFIG = {
"/api": {
"target": {
"host": "localhost",
"port": "10000",
"protocol": "https:",
"key": fs.readFileSync('ssl/data.key'),
"cert": fs.readFileSync('ssl/data.cert')
},
"secure": "false",
"rejectUnauthorized": "false",
"changeOrigin": true,
"logLevel": "debug"
}
};
module.exports = PROXY_CONFIG;
Это приводит к следующему выводу при запуске приложения:
[HPM] Proxy created: /api -> {
host: 'localhost',
port: '10000',
protocol: 'https:',
key: <Buffer 42 61 ... <many> more bytes>,
cert: <Buffer 42 61 ... <many> more bytes>
}
[HPM] Subscribed to http-proxy events: [ 'error', 'close' ]
Однако, как только фронт пытается получить доступ к бэкенду, я все равно получаю ту же ошибку:
[HPM] Error occurred while trying to proxy request /api/data from localhost:4201 to localhost (DEPTH_ZERO_SELF_SIGNED_CERT) (https://nodejs.org/api/errors.html#errors_common_system_errors)
У меня заканчиваются идеи, и Google не помог. Я не могу себе представить, что я первый, кто попробовал эту установку. Можно ли в любом случае указать прокси-серверу angular либо не заботиться о моем самоподписанном сертификате, либо сказать ему доверять этому сертификату?
Если я делаю ng build --prod
и mvn clean install
(что благодаря maven-resources-plugin
копирует папку dist
внешнего интерфейса в classes/static
символа, а затем запускает приложение Spring Boot с помощью java -jar data-0.0.1-SNAPSHOT.jar
, все работает:
Я могу получить доступ к данным с помощью своего браузера, перейдя на https://localhost:10000/api/data
и получить необработанные данные JSON. Я также могу перейти к https://localhost:10000/
, чтобы запустить свое угловое приложение, и у него не возникнет проблем с прямым доступом к вышеуказанным данным JSON через https.
Таким образом, моя установка работает в производстве, но я не могу запустить ее в своей конфигурации разработки с прокси-сервером angular.
Редактировать: чтобы сообщить об использовании предложений из статьи SO. Берк Куркчуоглу связан с
Насколько я могу судить, в этой статье описывается, как включить SSL (с чем у меня не было проблем), но тем не менее попробовать стоило:
Я добавил следующее в свой angular.json
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "data:build",
"hmrWarning": false,
"sslKey": "ssl/data.key",
"sslCert": "ssl/data.cert",
"ssl": true
}
},
Это приводит к тому, что я могу убрать параметры --ssl --ssl-cert <cert> --ssl-key <key>
из моей записи ng serve
в package.json, но прокси-сервер все равно выдает ту же ошибку.
DEPTH_ZERO_SELF_SIGNED_CERT
- person Urs Beeli   schedule 13.11.2020