セキュリティとWebSocketの紹介

1前書き

リンク:/websockets-spring[前の記事]では、Spring MVCプロジェクトにWebSocketを追加する方法を示しました。

ここでは、Spring MVCでSpring WebSocketにセキュリティを追加する方法について説明します。続行する前に、基本的なSpring MVCセキュリティの適用範囲がすでに整っていることを確認してください。そうでない場合は、リンク:/spring-security-basic-authentication[この記事]を調べてください。

2 Mavenの依存関係

WebSocket実装に必要なMavenの依存関係には、2つの主要なグループがあります。

まず、使用するSpring FrameworkとSpring Securityの包括的なバージョンを指定しましょう。

<properties>
    <spring.version>5.0.6.RELEASE</spring.version>
    <spring-security.version>5.0.6.RELEASE</spring-security.version>
</properties>

次に、基本的な認証と承認を実装するために必要なコアとなるSpring MVCおよびSpring Securityライブラリを追加しましょう。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${spring-security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring-security.version}</version>
</dependency>

spring-core の最新バージョン、 spring-web 、https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-webmvc%22[spring-webmvc]、https://search.maven。 org/classic/#検索%7Cga%7C1%7Cg%3A%22%20org.springframework%22%20AND%20a%3A%22spring-security-web%22[spring-security-web]、https://検索。 maven.org/classic/#search%7Cga%7C1%7Cg%3A%22%20org.springframework%22%20AND%20a%3A%22spring-security-config%22[spring-security-config]はMavenで見つけることができます中央です。

最後に、必要な依存関係を追加しましょう。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-messaging</artifactId>
    <version>${spring-security.version}</version>
</dependency>

spring-の最新バージョンを見つけることができます。 websocket 、https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-messaging%22[spring-messaging]、およびhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-security-messaging%22[spring-security-message]]Maven Central

3基本的なWebSocketセキュリティ

spring-security-messaging ライブラリを使用したWebSocket固有のセキュリティは、 AbstractSecurityWebSocketMessageBrokerConfigurer クラスとプロジェクト内でのその実装に集中します。

@Configuration
public class SocketSecurityConfig
  extends AbstractSecurityWebSocketMessageBrokerConfigurer {
     //...
}

AbstractSecurityWebSocketMessageBrokerConfigurer クラス は、__WebSecurityConfigurerAdapterによって提供された追加のセキュリティ適用範囲 を提供します。

spring-security-messaging ライブラリがWebSocketのセキュリティを実装する唯一の方法ではありません。通常の spring-websocket ライブラリを使い続けるなら、 WebSocketConfigurer インターフェースを実装し、セキュリティインターセプターをソケットハンドラにアタッチすることができます。

私たちは spring-security-messaging ライブラリを使用しているので、 AbstractSecurityWebSocketMessageBrokerConfigurer アプローチを使用します。

3.1. configureInbound() を実装する

configureInbound() の実装は、 AbstractSecurityWebSocketMessageBrokerConfigurer サブクラスを構成する上で最も重要なステップです。

@Override
protected void configureInbound(
  MessageSecurityMetadataSourceRegistry messages) {
    messages
      .simpDestMatchers("/secured/** ** ").authenticated()
      .anyMessage().authenticated();
}

WebSecurityConfigurerAdapter を使用すると、さまざまなルートに対してアプリケーション全体のさまざまな承認要件を指定できますが、 AbstractSecurityWebSocketMessageBrokerConfigurer を使用すると、ソケットの送信先に対して特定の承認要件を指定できます。

3.2. タイプと行き先のマッチング

MessageSecurityMetadataSourceRegistry を使用すると、パス、ユーザーロール、および許可されるメッセージなどのセキュリティ制約を指定できます。

  • 型マッチャーは、どの SimpMessageType が許可されているのか、そしてどのように :

.simpTypeMatchers(CONNECT, UNSUBSCRIBE, DISCONNECT).permitAll()
  • デスティネーションマッチャーはどのエンドポイントパターンがアクセス可能かを制限します そしてその方法は : **

.simpDestMatchers("/app/** ** ").hasRole("ADMIN")
  • 登録先のMatcherは、 SimpMessageType.SUBSCRIBEと一致する List of SimpDestinationMessageMatcher i __nstances をマップします。

.simpSubscribeDestMatchers("/topic/** ** ").authenticated()

4ソケットルートの固定

基本的なソケットセキュリティとタイプマッチングの設定が紹介されたので、ソケットセキュリティ、ビュー、STOMP(テキストメッセージングプロトコル)、メッセージブローカ、およびソケットコントローラを組み合わせて、Spring MVCアプリケーション内で安全なWebSocketを実現できます。

まず、Spring Securityの基本的な適用範囲について、ソケットビューとコントローラを設定しましょう。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableWebSecurity
@ComponentScan("com.baeldung.springsecuredsockets")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
          .antMatchers("/", "/index", "/authenticate").permitAll()
          .antMatchers(
            "/secured/** ** /** ** ",
            "/secured/success",
            "/secured/socket",
            "/secured/success").authenticated()
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login").permitAll()
          .usernameParameter("username")
          .passwordParameter("password")
          .loginProcessingUrl("/authenticate")
         //...
    }
}

次に、実際のメッセージ送信先に認証要件を設定しましょう。

@Configuration
public class SocketSecurityConfig
  extends AbstractSecurityWebSocketMessageBrokerConfigurer {
    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
          .simpDestMatchers("/secured/** ** ").authenticated()
          .anyMessage().authenticated();
    }
}

これで、WebSocketMessageBrokerConfigurerに実際のメッセージとSTOMPエンドポイントを登録できます。

@Configuration
@EnableWebSocketMessageBroker
public class SocketBrokerConfig
  implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/secured/history");
        config.setApplicationDestinationPrefixes("/spring-security-mvc-socket");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/secured/chat")
          .withSockJS();
    }
}

上記でセキュリティの対象となっているソケットコントローラの例とエンドポイントを定義しましょう。

@Controller
public class SocketController {

    @MessageMapping("/secured/chat")
    @SendTo("/secured/history")
    public OutputMessage send(Message msg) throws Exception {
        return new OutputMessage(
           msg.getFrom(),
           msg.getText(),
           new SimpleDateFormat("HH:mm").format(new Date()));
    }
}

5同一オリジンポリシー

  • 同一オリジンポリシー** は、エンドポイントとのすべての対話が対話が開始された同じドメインから来なければならないことを要求します。

例えば、あなたのWebSockets実装が foo.com でホストされていて、あなたが 同じ起源ポリシー を実施していると仮定しましょう。ユーザーが foo.com でホストされているクライアントに接続してから bar.com への別のブラウザを開くと、 bar.com はWebSocket実装にアクセスできなくなります。

5.1. 同じオリジンポリシーを上書きする

Spring WebSocketはそのままで同じOriginポリシーを適用しますが、通常のWebSocketは適用しません。

実際、Spring Securityでは、有効な CONNECT メッセージタイプに対してCSRF( Cross Site Request Forgery )トークンが必要です。

@Controller
public class CsrfTokenController {
    @GetMapping("/csrf")
    public @ResponseBody String getCsrfToken(HttpServletRequest request) {
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        return csrf.getToken();
    }
}

/csrf でエンドポイントを呼び出すことによって、クライアントはトークンを取得し、CSRFセキュリティ層を介して認証できます。

ただし、 AbstractSecurityWebSocketMessageBrokerConfigurer に次の設定を追加することで、Springの** 同一元ポリシーを上書きすることができます。

@Override
protected boolean sameOriginDisabled() {
    return true;
}

5.2. STOMP、SockJSサポート、および フレームオプション

Spring WebSocketのクライアント側サポートを実装するには、https://github.com/sockjs[SockJS]とともにhttp://jmesnil.net/stomp-websocket/doc/[STOMP]を使用するのが一般的です。

  • SockJSは、デフォルトではHTMLの iframe 要素による転送を許可しないように設定されています。これはクリックジャッキング** の脅威を防ぐためです。

ただし、 iframes がSockJSトランスポートを利用できるようにすると効果的な場合がある特定のユースケースがあります。これを行うには、 WebSecurityConfigurerAdapter のデフォルト設定をオーバーライドできます。

@Override
protected void configure(HttpSecurity http)
  throws Exception {
    http
      .csrf()
       //...
        .and()
      .headers()
        .frameOptions().sameOrigin()
      .and()
        .authorizeRequests();
}

この例では、 iframes を介したトランスポートを許可しているにもかかわらず、 Same Origin Policy に従っています。

6. Oauth2対象

標準的な WebSecurityConfigurerAdapter coverage _. _ link:/rest-api-spring-oauth2-anglejsに加えて - そして - これを拡張することによってOauth2セキュリティカバレッジを実装することによって、Oauth2特有のSpring WebSocketのサポートが可能になりますオース2。

WebSocketエンドポイントを認証してアクセスするには、クライアントからバックエンドWebSocketに接続するときにOauth2 access token__をクエリパラメータに渡します。

これがSockJSとSTOMPを使ったその概念を示す例です。

var endpoint = '/ws/?access__token=' + auth.access__token;
var socket = new SockJS(endpoint);
var stompClient = Stomp.over(socket);

7. 結論

この簡単なチュートリアルでは、Spring WebSocketにセキュリティを追加する方法を示しました。 Springのhttps://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html[WebSocket]およびhttp://docs.spring.io/autorepo/docs/を見てください。 spring-security/4.2.x/reference/html/websocket.html[WebSocket Security]この統合についてもっと知りたいならばへの参照ドキュメント。

いつものように、この記事で使われている例についてはhttps://github.com/eugenp/tutorials/tree/master/spring-security-mvc-socket[Githubプロジェクト]をチェックしてください。

前の投稿:ダガー2の紹介
次の投稿:The Baeldung Weekly Review 17