Editor PHP Zimo berada di sini untuk menjawab soalan sama ada penapis Spring Security memperoleh maklumat sesi daripada Redis. Spring Security ialah rangka kerja keselamatan yang berkuasa yang menyediakan set lengkap mekanisme pengesahan dan kebenaran. Secara lalai, Spring Security menggunakan HttpSession untuk mengurus maklumat sesi pengguna. Walau bagaimanapun, dengan konfigurasi, kami boleh menyimpan maklumat sesi dalam storan luaran seperti Redis. Kelebihan ini ialah ia dapat merealisasikan pengurusan sesi teragih dan meningkatkan kebolehskalaan sistem. Oleh itu, penapis Spring Security boleh mendapatkan maklumat sesi daripada Redis.
Saya cuba menggunakan spring-boot, spring-security dan spring-session untuk melaksanakan sistem log masuk dan menggunakan redis sebagai storan sesi.
Konfigurasi saya:
@enablewebsecurity @enablemethodsecurity @configuration @requiredargsconstructor public class securityconfig { private final userdetailsservice detailsservice; @bean public passwordencoder passwordencoder() { return new bcryptpasswordencoder(); } @bean public authenticationprovider authenticationprovider(passwordencoder passwordencoder) { daoauthenticationprovider provider = new daoauthenticationprovider(); provider.setpasswordencoder(passwordencoder); provider.setuserdetailsservice(this.detailsservice); return provider; } @bean public authenticationmanager authenticationmanager(authenticationprovider authenticationprovider) { return new providermanager(authenticationprovider); } @bean public securityfilterchain filterchain(httpsecurity http) throws exception { return http .csrf().disable() .cors(customizer.withdefaults()) .authorizehttprequests(auth -> { auth.requestmatchers("/api/v1/auth/register/**", "/api/v1/auth/login").permitall(); auth.anyrequest().authenticated(); }) .sessionmanagement(sessionmanagement -> sessionmanagement .sessioncreationpolicy(if_required) // .sessionfixation(sessionmanagementconfigurer.sessionfixationconfigurer::newsession) // .maximumsessions(100000) // //.sessionregistry(sessionregistry()) ) //.exceptionhandling((ex) -> ex.authenticationentrypoint(this.authentrypoint)) .logout(out -> out .logouturl("/api/v1/auth/logout") .invalidatehttpsession(true) // invalidate all sessions after logout .deletecookies("jsessionid") .logoutsuccesshandler((request, response, authentication) -> securitycontextholder.clearcontext() ) ) .build(); } @bean public securitycontextrepository securitycontextrepository() { return new httpsessionsecuritycontextrepository(); } }
Pengawal log masuk saya:
@postmapping("/login") public void login(@requestbody loginform form, httpservletrequest request, httpservletresponse response) { string ip = httprequestutil.getip(request); string device = httprequestutil.getdevice(request); loginformwrapper loginformwrapper = new loginformwrapper(form.email(), form.password(), ip, device); authenticationservice.login(loginformwrapper, request, response); }
dan perkhidmatan pengesahan:
@override public void login(loginformwrapper form, httpservletrequest request, httpservletresponse response) { authentication authentication = authenticationmanager.authenticate(usernamepasswordauthenticationtoken.unauthenticated( form.email().trim(), form.password())); // create a new context securitycontext context = securitycontextholder.createemptycontext(); context.setauthentication(authentication); // update securitycontextholder and strategy this.securitycontextholderstrategy.setcontext(context); this.securitycontextrepository.savecontext(context, request, response); }
Jika saya faham betul
this.securitycontextholderstrategy.setcontext(context);
Pengesahan hendaklah disimpan dalam ingatan aplikasi, cth. dalam konteks threadlocal
dan
`this.securitycontextrepository.savecontext(context, request, response);`
Maklumat sesi hendaklah disimpan ke redis.
Sekarang apabila saya log masuk saya melihat data telah disimpan ke redis:
Namun, apabila menyemak permintaan log masuk saya yang dikembalikan, saya melihat:
Id sesi yang sama sekali berbeza.
Soalan pertama saya ialah: Mengapa id ini tidak sepadan? Bagaimanakah musim bunga tahu kunci mana yang hendak dicari?
Soalan lain ialah: penapis apa untuk mendapatkan data daripada redis? Saya cuba nyahpepijat semua penapis dalam rantai penapis:
[org.springframework.security.web.session.DisableEncodeUrlFilter@2fedae96, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4945cd1f, org.springframework.security.web.context.SecurityContextHolderFilter@72499396, org.springframework.security.web.header.HeaderWriterFilter@7048d039, org.springframework.web.filter.CorsFilter@2dbfcbe4, org.springframework.security.web.authentication.logout.LogoutFilter@5d5a77de, org.springframework.security.web.session.ConcurrentSessionFilter@1f8e1096, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@651bec9a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@76d4e1af, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6f13ed1, org.springframework.security.web.session.SessionManagementFilter@642693c2, org.springframework.security.web.access.ExceptionTranslationFilter@2199e1a4, org.springframework.security.web.access.intercept.AuthorizationFilter@48c584c]
Tetapi ia seolah-olah membaca maklumat sesi dari httpserletrequest entah bagaimana - namun, jika saya mengeluarkan kunci daripada redis, pengesahan untuk titik akhir yang memerlukannya gagal.
Adakah saya terlepas sesuatu? Adakah saya mendapatkan semula maklumat sesi daripada redis dan menyimpannya dalam httpservlerrequest
sebelum jururawat saya bermula? Atau bagaimana ia membaca data redis?
Terima kasih atas bantuan anda.
Nilai dalam kuki sesi adalah dikodkan base64:
echo '3c048eae-9f73-4df5-a009-bdf802ae37ca' | openssl base64 m2mwndhlywutowy3my00zgy1lwewmdktymrmodayywuzn2nhcg==
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d 3c048eae-9f73-4df5-a009-bdf802ae37ca
Jadi apabila base64 dinyahkod, id sesi kuki sepadan dengan id sesi yang disimpan dalam redis.
Jika anda belum membacanya lagi, saya akan mengesyorkan dokumen ini: https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1
Terutama bahagian "Memahami Komponen Pengurusan Sesi": https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1#memahami-komponen-pengurusan-sesi
Anda tidak menyebut versi keselamatan musim bunga yang anda gunakan, tetapi saya rasa anda menggunakan keselamatan musim bunga 6. Dalam bahagian ini, terdapat ayat sedemikian yang berkaitan dengan pengesahan sesi:
Atas ialah kandungan terperinci Adakah penapis keselamatan musim bunga mendapat maklumat sesi daripada redis?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!