จัดการ HTTP Session ด้วย Spring Session + Redis
Session เป็นอีกเรื่งที่ Spring Framework รองรับด้วย Spring Session ที่สามารถจัดการกับ HTTP Session ได้ และมี data store ให้เลือกใช้ ตัวอย่างเช่น Redis, JDBC หรือ Hazelcast ซึ่งในบทความนี้ก็จะมาลองใช้งาน Spring Session อย่างง่ายซึ่งเก็บข้อมูลไว้บน Redis จัดการกับ Session ของ User Authentication 👨🏻💻
HTTP Session?
เป็นลำดับของ network request-response transaction ซึ่ง HTTP Client จะเริ่มการร้องขอ (Request) ด้วยการสร้าง TCP (Transmission Control Protocol) เชื่อมต่อกับ Port เฉพาะบน Server (โดยทั่วไปจะเป็น Port 80 แต่บางทีก็ใช้ Port 8080) ซึ่ง HTTP Server จะตรวจสอบบน Port นั้นสำหรับรอข้อความร้องขอของ Client เมื่อรับข้อความร้องแล้วขอ Server จะส่งสถานะกลับไป เช่น “HTTP/1.1 200 OK” พร้อมด้วยข้อความ
Spring Session
เป็น API และ implementation สำหรับจัดการกับ Session information ของผู้ใช้งาน (User) รองรับ clustered session โดยไม่ต้องอาศัย application container เฉพาะ โดยสามารถเชื่อมต่อกับ
- HttpSession — แทนที่
HttpSession
ใน application container (เช่น Tomcat) อีกทั้งยังรองรับ session ID ใน header เพื่อทำงานกับ RESTful API - WebSocket — สำหรับรักษา
HttpSession
ในการรับข้อความใน WebSocket - WebSession — แทนที่
WebSession
ของ WebFlux ใน application container
ในบทความนี้จะใช้ Spring Session ในการจัดการกับ HttpSession
โดยใช้ module Spring Session Data Redis
ซึ่งเป็นการใช้ Redis สำหรับเก็บข้อมูลของ Session ในฝั่ง Server สำหรับจัดการกับ User Authentication ด้วย Basic Auth
แต่ Spring Session รองรับการเก็บข้อมูลในรูปแบบ RDMS ด้วย JDBC และ Hazalcase อีกด้วย
Create Spring Boot project
ด้วย Spring Initializr ด้วยการเลื่อก dependencies เป็น Web, Security, Session และ Redis
แล้วใช้ IntelliJ หรือ IDE อื่นเปิด Spring Boot project จะเห็นได้ว่าในส่วนของ Dependencies ของ pom.xml จะมี dependency spring-session-data-redis
สำหรับใช้ Redis กับ HttpSession
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>....</dependencies>
เพิ่ม application configuration ให้กับ project สำหรับเชื่อมต่อกับ Redis ด้วย Spring Data ซึ่งเป็นการกำหนด Redis host
และ port
spring-redis.host=localhost
spring-redis.port=6379
Spring Session Configuration
สร้าง configuration สำหรับ Spring Session และ Redis ด้วยการใช้ annotation @EnableRedisHttpSession
และ AbstractHttpSessionApplicationInitializer
เป็นการ config สำหรับ Spring Boot auto configuration
Spring Security Configuration
สร้าง configuration สำหรับ Spring Security เพื่อใช้งาน Basic Auth ด้วย user ที่เป็น role ADMIN
และ user admin
และ password password
โดยที่อนุญาติให้ role ที่เป็น ADMIN
เท่านั้นที่ใช้งานได้ และใช้ authentication สำหรับ path /
Rest Controller
และสุดท้ายสร้าง RestController แบบง่ายๆ เพื่อให้ user สามารถใช้งาน RESTful API ได้ และตอบกลับเป็น “Hello Admin” ถ้า user ผ่าน authentication
Run Redis
เริ่มต้นการทำงานของ Redis server ด้วยคำสั่ง redis-server
Run Spring Boot App
เริ่มต้นการทำงานของ Spring Boot application ด้วยคำสั่ง mvn spring-boot:run
Test Application
เรามาทดสอบการทำงานของ Spring Session ด้วย Postman โดยที่เริ่มแรก request ไปที่ Spring Boot Application ด้วย No Auth (ไม่มี User credential) ก็จะได้ status code เป็น 401 Unauthorized
นั้นก็หมายความว่า Application ต้องการ User credential เพื่อ Authentication
เมื่อเรา request อีกครั้งด้วย ฺBasic Auth (มี User credential— username: admin, password: password) จะได้ status code เป็น 200 OK ซึ่งก็หมายความว่าสามารถ Authenticated ด้วย Basic Auth ได้
ถ้าเรา request อีกครั้งด้วย No Auth (ไม่มี User credential) เราก็จะได้ 200 OK
อยู่ นั้นหมายความว่า HTTP Session ของ Authentication ครั้งที่แล้วยังอยู่
ตรวจสอบ Session บน Redis ด้วย Redis-CLI โดยใช้คำสั่ง KEYS *
เพื่อดูว่ามี key ของ Session อยู่ใน Redis หรือไม่ จะเห็นได้ว่ามี key session อยู่
ลบ Session ทั้งหมดด้วยคำสั่ง FLUSHALL
และใช้คำสั่ง KEYS *
อีกครั้งเพื่อดูว่ายังมี key session อยู่ไหม จะเห็นได้ว่าไม่มีอยู่แล้ว
เมื่อเรา request แบบ No Auth อีกครั้งจากที่ได้เมื่อสักครู่ก็จะเห็นว่าตอนนี้ได้ status code เป็น 401 Unauthorized
ซึ่งก็คือไม่มี session บน Application แล้วเมื่อ request ไปอีกครั้งก็จะไม่อนุญาติให้ใช้งาน Application
สรุป
จากบทความนี้ใช้ Spring Session สำหรับจัดการกับ HTTP Session และเก็บข้อมูลเป็น cache ไว้บน Redis นั้นด้วยพลังของ Spring framework ทำให้เราสามารถพัฒนา application ได้ง่ายด้วยการ Config เพียงเล็กน้อยเท่านั้น แต่ก็ยังมีคุณสมบัติอื่นๆ อีกของ Spring Session ที่บทความนี้ยังไม่ได้กล่าวถึง ก็สามารถไปลองกันได้ 🤪