[JAVA] Spring Security-Nutzungsnotiz CORS

Grundlegende und systematische Geschichte Zertifizierungs- / Autorisierungsgeschichte Remember-Me-Geschichte CSRF-Geschichte Session Management Story Die Geschichte des Antwortheaders Method Security Story Die Geschichte von Run-As Die Geschichte von ACL Teststory Sprechen Sie über die Zusammenarbeit mit MVC und Boot

Sonderedition Was Spring Security kann und was nicht

Was ist CORS?

@ tomoyukilabs 'CORS Summary --Qiita war eine Lernerfahrung.

Grob zusammengefasst

Es fühlt sich an wie.

Was ist "Herkunft"?Definition des Ursprungs|Gleiche Ursprungspolitik-Web-Sicherheit| MDNSehen.

Hello World

Vorbereiten von Seiten für den Zugriff mit Cross Origin

Platzieren Sie das folgende HTML auf GitHub, damit es im Browser als statische Seite geöffnet werden kann.

python


<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>cors test</title>
  </head>
  <body>
    <div>
      <select id="contextPath">
        <option value="namespace" selected>namespace</option>
        <option value="java-config">java-config</option>
      </select>
    </div>

    <div>
      <input id="headerName" placeholder="Header-Name" />
      <input id="headerValue" placeholder="Header-Value" />
    </div>

    <div>
      <input id="responseHeaderName" placeholder="responseHeaderName" />
    </div>

    <button type="button" id="sendButton">Send Request</button>

    <script src="https://code.jquery.com/jquery-3.2.1.min.js"
            integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
            crossorigin="anonymous"></script>

    <script>
      $(function() {
        $('#sendButton').on('click', function() {
          var headers = {};
          var headerName = $('#headerName').val();
          var headerValue = $('#headerValue').val();
          if (headerName) {
            headers[headerName] = headerValue;
          }

          var contextPath = $('#contextPath').val();

          $.ajax({
            url: 'http://localhost:8080/' + contextPath + '/cors',
            type: 'GET',
            dataType: 'text',
            headers: headers
          })
          .done(function(text, status, jqXhr) {
            console.log("text = " + text);

            var responseHeaderName = $('#responseHeaderName').val();
            if (responseHeaderName) {
              console.log("[ResponseHeader] " + responseHeaderName + " : " + jqXhr.getResponseHeader(responseHeaderName));
            }
          })
          .fail(function() {
            console.error(arguments);
          });
        });
      });
    </script>
  </body>
</html>

Der tatsächlich auf GitHub gepostete

Ich versuche mit Ajax auf localhost zuzugreifen.

Serverseitige Implementierung

CorsServlet.java


package sample.spring.security.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/cors")
public class CorsServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Original-Header", "CORS!!");
        try (PrintWriter writer = resp.getWriter()) {
            writer.println("Hello CORS!!");
        }
    }
}

Eine Implementierung, die nur den entsprechenden Header und Textkörper zurückgibt.

Versuchen Sie zunächst, ohne CORS einzustellen

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
    </sec:http>

    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user name="hoge" password="hoge" authorities="" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.eraseCredentials(false)
            .inMemoryAuthentication()
                .withUser("hoge")
                .password("hoge")
                .roles();
    }
}

Es wurden keine Einstellungen für CORS vorgenommen.

Wenn ich auf der Bestätigungsseite auf die Schaltfläche "Anfrage senden" klicke, wird folgende Fehlermeldung angezeigt: ..

spring-security.jpg

Ich wurde durch die Authentifizierungsprüfung von Spring Security blockiert und auf die Anmeldeseite umgeleitet.

Es heißt auch, dass nicht darauf zugegriffen werden kann, da der in der CORS-Spezifikation definierte Header "Access-Control-Allow-Origin" in der Antwort fehlt.

Ändern Sie die Spring Security-Einstellungen, um sie zugänglich zu machen

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">
    
    <bean id="corsConfiguration" class="org.springframework.web.cors.CorsConfiguration">
        <property name="allowedOrigins">
            <list>
                <value>http://opengl-8080.github.io</value>
            </list>
        </property>
        <property name="allowedMethods">
            <list>
                <value>GET</value>
            </list>
        </property>
    </bean>

    <bean id="corsSource" class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
        <property name="corsConfigurations">
            <map>
                <entry key="/cors" value-ref="corsConfiguration" />
            </map>
        </property>
    </bean>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/cors" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:cors configuration-source-ref="corsSource" />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/cors").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .cors()
                .configurationSource(this.corsConfigurationSource());
    }

    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedMethod("GET");
        corsConfiguration.addAllowedOrigin("http://opengl-8080.github.io");

        UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
        corsSource.registerCorsConfiguration("/cors", corsConfiguration);

        return corsSource;
    }

    ...
}

Führe es nochmals aus.

spring-security.jpg

Diesmal war der Zugriff erfolgreich und der vom Server zurückgegebene Text kann ausgegeben werden.

Erläuterung

CORS aktivieren

applicationContext.xml


    <bean id="corsSource" class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
        ...
    </bean>
    
    <sec:http>
        ...
        <sec:cors configuration-source-ref="corsSource" />
    </sec:http>

MySpringSecurityConfig.java


    @Override
    public void configure(HttpSecurity http) throws Exception {
        http...
                .and()
            .cors()
                .configurationSource(this.corsConfigurationSource());
    }

    private CorsConfigurationSource corsConfigurationSource() {
        ...
    }

CORS-Einstellungen

applicationContext.xml


    <bean id="corsConfiguration" class="org.springframework.web.cors.CorsConfiguration">
        <property name="allowedOrigins">
            <list>
                <value>http://opengl-8080.github.io</value>
            </list>
        </property>
        <property name="allowedMethods">
            <list>
                <value>GET</value>
            </list>
        </property>
    </bean>

    <bean id="corsSource" class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
        <property name="corsConfigurations">
            <map>
                <entry key="/cors" value-ref="corsConfiguration" />
            </map>
        </property>
    </bean>

--Verwenden Sie zwei Klassen, um CORS zu konfigurieren --CorsConfigurationSource und CorsConfiguration

MySpringSecurityConfig.java


    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedMethod("GET");
        corsConfiguration.addAllowedOrigin("http://opengl-8080.github.io");

        UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
        corsSource.registerCorsConfiguration("/cors", corsConfiguration);

        return corsSource;
    }

Entspricht der Preflight-Anfrage

Die CORS-Spezifikation begrenzt die HTTP-Methoden und konfigurierbaren Header, die standardmäßig zulässig sind.

Wenn Sie einen Header senden möchten, der standardmäßig nicht zulässig ist, müssen Sie eine Prefilight-Anforderung senden, eine Prefilight-Anforderung, um zu überprüfen, ob dies zulässig ist.

Der Client sendet die Produktionsanforderung nur, wenn der Server dieser Anforderung "OK" zurückgibt.

Versuchen Sie zunächst, einen nicht zulässigen HTTP-Header zu senden

spring-security.jpg

Versuchen Sie, eine Anfrage mit einem nicht autorisierten Header namens "Hoge" zu senden.

spring-security.jpg

Ich war sehr wütend.

Es heißt, dass nicht darauf zugegriffen werden konnte, da in der Preflight-Anforderung ein Header vorhanden war, der nicht zulässig war.

Überprüfen Sie die Anforderungs- und Antwortheader.

spring-security.jpg

Der Anforderungsheader lautet "Access-Control-Request-Headers: hoge", und ich überprüfe, ob der Header "hoge" zulässig ist. Die Antwort enthält jedoch keinen Header, der besagt, dass "hoge" zulässig ist.

Aus diesem Grund stellt der Browser fest, dass "hoge" ein nicht autorisierter Header ist, und setzt die Verarbeitung aus.

Hoge-Header zulassen

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    <bean id="corsConfiguration" class="org.springframework.web.cors.CorsConfiguration">
        <property name="allowedOrigins">
            <list>
                <value>http://opengl-8080.github.io</value>
            </list>
        </property>
        <property name="allowedMethods">
            <list>
                <value>GET</value>
            </list>
        </property>
        <property name="allowedHeaders">★ Ergänzung
            <list>
                <value>Hoge</value>
            </list>
        </property>
    </bean>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

...

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    ...

    private CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        ...
        corsConfiguration.addAllowedHeader("Hoge");★ Ergänzung

        ...
    }

    ...
}

"Hoge" wird in "CorsConfiguration" zu "allowHeader" hinzugefügt.

Überprüfen Sie den Vorgang erneut.

spring-security.jpg

Diesmal wurde die Anfrage ordnungsgemäß bestanden.

Überprüfen Sie den Status der HTTP-Anforderung.

spring-security.jpg

Die Preflight-Anforderung durch die "OPTIONS" -Methode wird zuerst ausgeführt, und dann wird die Anforderung durch die Produktion "GET" gesendet.

Schauen Sie sich die Kopfzeile für "OPTIONEN" an.

spring-security.jpg

"Access-Control-Allow-Headers: hoge" wurde dem Antwortheader hinzugefügt, um anzuzeigen, dass der "hoge" -Header zulässig ist.

Spring Security reagiert automatisch auf Preflight-Anfragen gemäß den in CorsConfiguration festgelegten Berechtigungsregeln.

Es gibt standardmäßig Einschränkungen, wenn Clients auf beliebige Antwortheader zugreifen, aber exponierte Header. Dies kann durch Festlegen von CorsConfiguration.html # addExposedHeader-java.lang.String-) zugelassen werden.

Referenz

Recommended Posts

Spring Security-Nutzungsnotiz CORS
Spring Security-Nutzungsnotiz CSRF
Spring Security-Nutzungsnotiz Run-As
Sicherheit der Verwendungsnotizmethode für Spring Security
Spring Security-Nutzungsnotiz Remember-Me
Spring Security-Verwendungsnotiztest
Spring Security-Nutzungsnotiz Authentifizierung / Autorisierung
Antwortheader für die Verwendung von Spring Security
Sitzungsverwaltung für Spring Security-Nutzungsnotizen
Spring Security-Nutzungsnotiz Basic / Mechanismus
Spring Security Usage Memo Domänenobjektsicherheit (ACL)
Hinweise zur Verwendung von Spring Shell
Verwendungshinweis zu Spring Security: Zusammenarbeit mit Spring MVC und Boot
Frühlingsrückblick Memo
Verwendungshinweise zu JavaParser
Hinweise zur Verwendung von WatchService
Verwendungshinweise zu JUnit5
JJUG CCC Frühjahr 2018 Memo
Informationen zur Spring Security-Authentifizierung
Schreiben von Frühlingsstiefel-Memos (1)
Spring Security erhöht 403 verboten
Schreiben von Spring Boot-Memos (2)
[Persönliche Notizen] Über das Spring Framework
JJUG CCC 2018 Frühlingsbeteiligungsprotokoll
Spring Framework Selbststudium Memo series_1
Anmeldefunktion mit Spring Security
Hinweise zur Verwendung des Abhängigkeitsmanagement-Plugins
Versuchen Sie es mit Spring Boot Security
Memo zur Spring Boot Controller-Methode
◆ Konstruktionsnotiz für Spring Boot + Gradle-Umgebung
JCA-Verwendungsprotokoll (Java Encryption Architecture)
Implementierte Authentifizierungsfunktion mit Spring Security ③
Spring Boot Tutorial Verwenden der Spring Security-Authentifizierung
Frühlingsrahmen Einfaches Studienmemo (2): AOP
Implementierte Authentifizierungsfunktion mit Spring Security ①
Erfahren Sie mehr über die Architektur der Spring Security-Authentifizierungsverarbeitung
Memo nach dem ersten Frühjahrsprojekt-MVC-
Ein Memo, das Spring Boot berührte
Frühjahr gründliche Einführung Version Upgrade Memo
Zertifizierung / Autorisierung mit Spring Security & Thymeleaf
Memo nach dem ersten Frühjahrsprojekt-Datenbank-
Verwendung von Thymeleaf mit Spring Boot