Веб-сокеты на загрузочном веб-сайте Spring, размещенном на Azure, возвращают ошибку 503/403 - PullRequest
2 голосов
/ 31 мая 2019

Я создал веб-приложение для Spring Boot, используя Spring Security с аутентификацией Azure AD и веб-сокетами для связи с клиентами. Локально это работает отлично, но при развертывании его в качестве веб-приложения Azure происходит сбой соединения Websocket с ошибками 503 и 403.

Я пытался найти ответы и здесь, и в Google. Некоторые ответы указывают на настройку приложения, в которой вы можете переключать поддержку веб-сокетов в веб-приложении на Azure, но эта настройка больше не доступна. Многие решения, которые я нашел, имеют возраст около 5 лет и мало соответствуют моей ситуации.

Я поделюсь некоторым кодом, но он довольно простой и в основном взят из руководств онлайн от Microsoft и Spring.

Jacascript, который подключается к конечной точке websocket:

stompClient = Stomp.over(socket);
stompClient.connect({}, onConnected, onError);  

Моя конфигурация веб-сокета:

import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer  {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();

    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/app");
        registry.enableSimpleBroker("/topic");
    }
}

Конфигурация Websecurity:

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);
        http.headers().frameOptions().disable();
    }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.groupId</groupId>
    <artifactId>artifactId</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Name</name>
    <description>This is a description</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-active-directory-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-webapp-maven-plugin</artifactId>
                <version>1.5.4</version>
                <configuration>
                    <deploymentType>jar</deploymentType>

                    <!-- configure app to run on port 80, required by App Service -->
                    <appSettings>
                        <property>
                            <name>JAVA_OPTS</name>
                            <value>-Dserver.port=80</value>
                        </property>
                    </appSettings>

                    <!-- Web App information -->
                    <resourceGroup>myResourceGroup</resourceGroup>
                    <appName>myAppName</appName>
                    <region>myRegion</region>
                    <pricingTier>S1</pricingTier>
                    <!-- Java Runtime Stack for Web App on Linux -->
                    <linuxRuntime>jre8</linuxRuntime>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-spring-boot-bom</artifactId>
                <version>2.1.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

Я ожидаю, что websocket подключится так же, как и локально, но я получаю ответное сообщение об ошибке 503:

Content-Length: 260
Content-Type: text/html
ETag: "5ce7bd82-104"
Server: nginx
Date: Fri, 31 May 2019 07:59:58 GMT

Далее следуют:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json;charset=UTF-8
Expires: 0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Date: Fri, 31 May 2019 07:59:59 GMT

Edit: Если я перехожу на запрошенный URL-адрес напрямую, я получаю сообщение об ошибке Can "Upgrade" only to "WebSocket".

Edit2: Если я подключу журналы своего веб-приложения в клиенте Azure, появится следующее сообщение:

0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 975], outboundChannel[pool
 size = 0, active threads = 0, queued tasks = 0, completed tasks = 325], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 53124]```

1 Ответ

0 голосов
/ 02 июня 2019

Похоже, что вы запускаете контейнер веб-приложения, если настройки веб-сокета не отображаются. Чтобы включить WebSocket, запустите приведенный ниже командлет для своего сайта и сообщите нам свои результаты.

    az webapp config set --web-sockets-enabled true --name <sitename> --resource-group <resourcegroupname>
...