Panduan untuk Sesi Musim Bunga

REST Teratas

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS

1. Gambaran keseluruhan

Spring Session mempunyai tujuan mudah untuk membebaskan pengurusan sesi dari batasan sesi HTTP yang disimpan di pelayan.

Penyelesaiannya memudahkan untuk berkongsi data sesi antara perkhidmatan di cloud tanpa terikat pada satu wadah (iaitu Tomcat). Selain itu, ia menyokong beberapa sesi dalam penyemak imbas yang sama dan menghantar sesi dalam tajuk.

Dalam artikel ini, kami akan menggunakan Spring Session untuk menguruskan maklumat pengesahan dalam aplikasi web. Walaupun Spring Session dapat mengekalkan data menggunakan JDBC, Gemfire, atau MongoDB, kami akan menggunakan Redis .

Untuk pengenalan kepada Redis, baca artikel ini.

2. Projek Mudah

Mari buat projek Spring Boot yang ringkas untuk dijadikan contoh contoh sesi kami di kemudian hari:

 org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE     org.springframework.boot spring-boot-starter-security   org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-test test  

Aplikasi kami dijalankan dengan Spring Boot dan induk pom menyediakan versi untuk setiap entri. Versi terbaru dari setiap kebergantungan boleh didapati di sini: spring-boot-starter-security, spring-boot-starter-web, spring-boot-starter-test.

Mari juga tambahkan beberapa sifat konfigurasi untuk pelayan Redis kami di application.properties :

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

3. Konfigurasi Spring Boot

Untuk Spring Boot, cukup untuk menambahkan kebergantungan berikut , dan konfigurasi automatik akan menguruskan selebihnya:

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

Kami menggunakan boot induk pom untuk menetapkan versi di sini, jadi ini dijamin berfungsi dengan pergantungan kami yang lain. Versi terbaru dari setiap kebergantungan boleh didapati di sini: spring-boot-starter-data-redis, spring-session.

4. Standard Spring Config (tanpa Boot)

Mari kita lihat juga pengintegrasian dan konfigurasi sesi spring tanpa Spring Boot - hanya dengan Spring biasa.

4.1. Kebergantungan

Pertama, jika kita menambah sesi musim bunga ke projek Spring standard, kita perlu menentukan secara jelas:

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

Versi terbaru dari modul-modul ini boleh didapati di sini: spring-session, spring-data-redis.

4.2. Konfigurasi Sesi Musim Bunga

Sekarang mari kita tambahkan kelas konfigurasi untuk Spring Session :

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

@EnableRedisHttpSession dan lanjutan AbstractHttpSessionApplicationInitializer akan membuat dan memasang penapis di hadapan semua infrastruktur keselamatan kami untuk mencari sesi aktif dan mengisi konteks keselamatan dari nilai yang disimpan di Redis .

Sekarang mari lengkapkan aplikasi ini dengan pengawal dan konfigurasi keselamatan.

5. Konfigurasi Aplikasi

Arahkan ke fail aplikasi utama kami dan tambahkan pengawal:

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

Ini akan memberi kita titik akhir untuk diuji.

Seterusnya, tambahkan kelas konfigurasi keselamatan kami:

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin") .password(passwordEncoder().encode("password")) .roles("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http .httpBasic().and() .authorizeRequests() .antMatchers("/").hasRole("ADMIN") .anyRequest().authenticated(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

Ini melindungi titik akhir kami dengan pengesahan asas dan menyediakan pengguna untuk diuji.

6. Ujian

Akhirnya, mari kita menguji semuanya - kami akan menentukan ujian mudah di sini yang membolehkan kami melakukan 2 perkara:

  • menggunakan aplikasi web langsung
  • bercakap dengan Redis

Mari kita aturkan perkara pertama:

public class SessionControllerTest { private Jedis jedis; private TestRestTemplate testRestTemplate; private TestRestTemplate testRestTemplateWithAuth; private String testUrl = "//localhost:8080/"; @Before public void clearRedisData() { testRestTemplate = new TestRestTemplate(); testRestTemplateWithAuth = new TestRestTemplate("admin", "password", null); jedis = new Jedis("localhost", 6379); jedis.flushAll(); } }

Perhatikan bagaimana kita menyiapkan kedua-dua klien ini - klien HTTP dan yang Redis. Sudah tentu, pada ketika ini pelayan (dan Redis) harus aktif dan beroperasi - supaya kita dapat berkomunikasi dengan mereka melalui ujian ini.

Mari kita mulakan dengan menguji bahawa Redis kosong:

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

Sekarang uji bahawa keselamatan kami mengembalikan 401 untuk permintaan yang tidak disahkan:

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

Seterusnya, kami menguji bahawa Spring Session menguruskan token pengesahan kami:

@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 }

First, our test confirms that our request was successful using the admin authentication credentials.

Then we extract the session value from the response headers and use it as our authentication in our second request. We validate that, and then clear all the data in Redis.

Finally, we make another request using the session cookie and confirm that we are logged out. This confirms that Spring Session is managing our sessions.

7. Conclusion

Spring Session is a powerful tool for managing HTTP sessions. With our session storage simplified to a configuration class and a few Maven dependencies, we can now wire up multiple applications to the same Redis instance and share authentication information.

Seperti biasa, semua contoh boleh didapati di Github.

REST bawah

Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:

>> SEMAK KURSUS