Leitfaden für die Frühjahrssitzung

Leitfaden für die Frühjahrssitzung

1. Überblick

Spring Session hat das einfache Ziel, Sitzungsverwaltung von den Einschränkungen der auf dem Server gespeicherten HTTP-Sitzung zu befreien.

Die Lösung erleichtert die gemeinsame Nutzung von Sitzungsdaten zwischen Diensten in der Cloud, ohne an einen einzelnen Container gebunden zu sein (d. H. Kater). Darüber hinaus werden mehrere Sitzungen im selben Browser und das Senden von Sitzungen in einem Header unterstützt.

In diesem Artikel verwenden wirSpring Session, um Authentifizierungsinformationen in einer Web-App zu verwalten. WährendSpring Session Daten mit JDBC, Gemfire oder MongoDB beibehalten können, verwenden wirRedis.

Eine Einführung inRedisfinden Sie im Artikel zuthis.

2. Ein einfaches Projekt

Erstellen wir zunächst ein einfachesSpring Boot-Projekt, das später als Basis für unsere Sitzungsbeispiele verwendet wird:


    org.springframework.boot
    spring-boot-starter-parent
    1.4.0.RELEASE
    



    
        org.springframework.boot
        spring-boot-starter-security
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    

Unsere Anwendung wird mitSpring Boot ausgeführt und der übergeordnete POM bietet Versionen für jeden Eintrag. Die neueste Version jeder Abhängigkeit finden Sie hier:spring-boot-starter-security,spring-boot-starter-web,spring-boot-starter-test.

Fügen wir auch einige Konfigurationseigenschaften für unseren Redis-Server inapplication.properties hinzu:

spring.redis.host=localhost
spring.redis.port=6379

3. Spring Boot-Konfiguration

Lassen Sie uns zunächst die Konfiguration vonSpring Session mit Boot demonstrieren.

Hinweis: Die Abschnitte 3 und 4 müssen nicht ausgefüllt werden. Wählen Sie einfach eine aus, je nachdem, ob SieSpring Boot zum Konfigurieren vonSpring Session verwenden oder nicht.

3.1. Abhängigkeiten

Fügen Sie unserem Projekt diese Abhängigkeiten hinzu:


    org.springframework.boot
    spring-boot-starter-data-redis


    org.springframework.session
    spring-session

Wir verwenden das übergeordnete Boot-POM, um die Versionen hier festzulegen, damit diese garantiert mit unseren anderen Abhängigkeiten funktionieren. Die neueste Version jeder Abhängigkeit finden Sie hier:spring-boot-starter-data-redis,spring-session.

3.2. Konfiguration der Frühlingssitzung

Fügen wir nun eine Konfigurationsklasse fürSpring Session hinzu:

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
}

4. Standard Spring Config (kein Boot)

Schauen wir uns auch die Integration und Konfiguration vonspring-session ohne Spring Boot an - nur mit einfachem Spring.

4.1. Abhängigkeiten

Wenn wir einem Standard-Spring-Projektspring-session hinzufügen, müssen wir zunächst explizit definieren:


    org.springframework.session
    spring-session
    1.2.2.RELEASE


    org.springframework.data
    spring-data-redis
    1.5.0.RELEASE

Die neuesten Versionen dieser Module finden Sie hier:spring-session,spring-data-redis

4.2. Konfiguration der Frühlingssitzung

Fügen wir nun eine Konfigurationsklasse fürSpring Session hinzu:

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
    @Bean
    public JedisConnectionFactory connectionFactory() {
        return new JedisConnectionFactory();
    }
}

Wie Sie sehen, sind die Unterschiede minimal - wir müssen jetzt nur noch unsereJedisConnectionFactory Bean explizit definieren - Boot erledigt dies für uns.

Bei beiden Typen@EnableRedisHttpSession und der Erweiterung vonAbstractHttpSessionApplicationInitializer wird ein Filter vor unserer gesamten Sicherheitsinfrastruktur erstellt und verkabelt, um nach aktiven Sitzungen zu suchen und den Sicherheitskontext anhand der inRedis gespeicherten Werte zu füllen .

Vervollständigen wir diese Anwendung jetzt mit einem Controller und der Sicherheitskonfiguration.

5. Anwendungskonfiguration

Navigieren Sie zu unserer Hauptanwendungsdatei und fügen Sie einen Controller hinzu:

@RestController
public class SessionController {
    @RequestMapping("/")
    public String helloAdmin() {
        return "hello admin";
    }
}

Dies gibt uns einen Endpunkt zum Testen.

Fügen Sie als Nächstes unsere Sicherheitskonfigurationsklasse hinzu:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("admin").password("password").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .httpBasic().and()
          .authorizeRequests()
          .antMatchers("/").hasRole("ADMIN")
          .anyRequest().authenticated();
    }
}

Dies schützt unsere Endpunkte mit der Basisauthentifizierung und richtet einen Benutzer zum Testen ein.

6. Test

Lassen Sie uns zum Schluss alles testen - wir definieren hier einen einfachen Test, mit dem wir zwei Dinge tun können:

  • verbrauchen die Live-Webanwendung

  • Sprich mit Redis

Lassen Sie uns zunächst Folgendes einrichten:

public class SessionControllerTest {

    private Jedis jedis;
    private TestRestTemplate testRestTemplate;
    private TestRestTemplate testRestTemplateWithAuth;
    private String testUrl = "http://localhost:8080/";

    @Before
    public void clearRedisData() {
        testRestTemplate = new TestRestTemplate();
        testRestTemplateWithAuth = new TestRestTemplate("admin", "password", null);

        jedis = new Jedis("localhost", 6379);
        jedis.flushAll();
    }
}

Beachten Sie, wie wir diese beiden Clients einrichten - den HTTP-Client und den Redis-Client. Zu diesem Zeitpunkt sollten natürlich der Server (und Redis) betriebsbereit sein, damit wir über diese Tests mit ihnen kommunizieren können.

Beginnen wir mit dem Testen, dassRedis leer ist:

@Test
public void testRedisIsEmpty() {
    Set result = jedis.keys("*");
    assertEquals(0, result.size());
}

Testen Sie nun, ob unsere Sicherheit einen 401 für nicht authentifizierte Anforderungen zurückgibt:

@Test
public void testUnauthenticatedCantAccess() {
    ResponseEntity result = testRestTemplate.getForEntity(testUrl, String.class);
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
}

Als Nächstes testen wir, dassSpring Session unser Authentifizierungstoken verwaltet:

@Test
public void testRedisControlsSession() {
    ResponseEntity result = testRestTemplateWithAuth.getForEntity(testUrl, String.class);
    assertEquals("hello admin", result.getBody()); //login worked

    Set redisResult = jedis.keys("*");
    assertTrue(redisResult.size() > 0); //redis is populated with session data

    String sessionCookie = result.getHeaders().get("Set-Cookie").get(0).split(";")[0];
    HttpHeaders headers = new HttpHeaders();
    headers.add("Cookie", sessionCookie);
    HttpEntity httpEntity = new HttpEntity<>(headers);

    result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
    assertEquals("hello admin", result.getBody()); //access with session works worked

    jedis.flushAll(); //clear all keys in redis

    result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
    //access denied after sessions are removed in redis
}

Zunächst wird durch unseren Test bestätigt, dass unsere Anforderung erfolgreich war, indem die Anmeldeinformationen für die Administratorauthentifizierung verwendet wurden.

Dann extrahieren wir den Sitzungswert aus den Antwortköpfen und verwenden ihn als Authentifizierung in unserer zweiten Anforderung. Wir validieren das und löschen dann alle Daten inRedis.

Zum Schluss stellen wir eine weitere Anfrage mithilfe des Sitzungscookies und bestätigen, dass wir abgemeldet sind. Dies bestätigt, dassSpring Session unsere Sitzungen verwaltet.

7. Fazit

Spring Session ist ein leistungsstarkes Tool zum Verwalten von HTTP-Sitzungen. Da unser Sitzungsspeicher auf eine Konfigurationsklasse und einige Maven-Abhängigkeiten vereinfacht ist, können wir jetzt mehrere Anwendungen mit derselbenRedis-Instanz verbinden und Authentifizierungsinformationen gemeinsam nutzen.

Wie immer finden Sie den Quellcodeover on Github.