關(guān)于SpringSecurity?Context?中獲取和更改當(dāng)前用戶信息的問題
SpringSecurity Context 獲取和更改用戶信息的問題
SecurityContext 異步線程中獲取用戶信息
今天在做項(xiàng)目時(shí)遇到了一個(gè)問題,我需要獲取當(dāng)前用戶的 ID。之前,前端并沒有存儲(chǔ)用戶信息,我一直是在后端的 service
中通過 SecurityContext
來獲取用戶信息,這個(gè)方法之前一直有效。然而,今天在另一個(gè) service
中調(diào)用時(shí)卻無法獲取到用戶信息。
經(jīng)過詳細(xì)排查,發(fā)現(xiàn) SecurityContext
的內(nèi)容是與請(qǐng)求線程(如 HTTP 請(qǐng)求)綁定的。但我當(dāng)前的 service
是用于處理 MQTT 消息,這屬于異步線程。因此,在異步線程中無法從 SecurityContext
獲取用戶信息,只能另尋解決方案。
/** * 處理接收到的設(shè)備數(shù)據(jù),根據(jù)數(shù)據(jù)類型進(jìn)行不同的處理。energy數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫,其他數(shù)據(jù)通過WebSocket發(fā)送到前端展示。 * @param data 數(shù)據(jù)內(nèi)容 */ private void handleIncomingData(String data) { ...... /* * 通過設(shè)備ID找到用戶ID, 不能通過securityContext獲取當(dāng)前用戶ID,因?yàn)檫@里是異步處理消息,不在請(qǐng)求線程中。 * 通過securityContext獲取當(dāng)前用戶ID的方法只能在請(qǐng)求線程中使用,通常是與HTTP請(qǐng)求相關(guān)的操作才能獲取到。 * 這里是MQTT消息處理,不在請(qǐng)求線程中,所以要通過其他方式獲取當(dāng)前用戶ID。 * 還因?yàn)檫@里是存入數(shù)據(jù)庫,因?yàn)橐膊荒芤蕾囄锢碓O(shè)備的用戶ID,設(shè)備不一定是存用戶ID, 降低耦合性。 TODO: 這里是否可以改進(jìn)? */ long userId = deviceMapper.findDeviceById(deviceId).getUserId(); if (userId<=0) {//如果userId<=0,說明沒有找到對(duì)應(yīng)的設(shè)備 logger.error("Failed to get user id by device id: {}", deviceId); throw new RuntimeException("Failed to get user id by device id: " + deviceId); } Energy energy = new Energy(); energy.setDeviceId(deviceId); energy.setEnergy(totalEnergy); energy.setRecordDate(recordDate); energy.setUserId(userId); ...... }
SecurityContext 線程降級(jí)問題
在項(xiàng)目中遇到 SecurityContext
線程降級(jí)的問題,具體場(chǎng)景是用戶修改個(gè)人資料(如郵箱)后,我希望 SecurityContext
中的用戶信息能及時(shí)更新。然而,在修改郵箱后,用戶需要跳轉(zhuǎn)到郵箱驗(yàn)證碼驗(yàn)證頁面,該頁面通過 security
配置中的 permitAll()
允許匿名訪問。
這個(gè)配置導(dǎo)致一個(gè)問題:雖然用戶已經(jīng)登錄認(rèn)證,但在訪問 /verify-code
頁面時(shí),SecurityContext
中的身份會(huì)被降級(jí)為匿名用戶,進(jìn)而導(dǎo)致更新后的信息沒有在 SecurityContext
中及時(shí)反映。
我了解到可以通過 setAuthentication()
手動(dòng)更新 SecurityContext
,但嘗試后依然無法解決問題,更新后的用戶信息仍舊無法及時(shí)同步到 SecurityContext
中~
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) // disable csrf .authorizeHttpRequests(authorize -> authorize .requestMatchers("/login","/register","/verify-code","/forgot-password","/change-password").permitAll()// permit request without authentication .requestMatchers("/ws/**").permitAll()// permit websocket request without authentication .anyRequest().authenticated() ) .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class) .logout(AbstractHttpConfigurer::disable);// disable logout otherwise it will conflict with our custom logout return http.build(); }
到此這篇關(guān)于SpringSecurity Context 中 獲取 和 更改 當(dāng)前用戶信息的問題的文章就介紹到這了,更多相關(guān)SpringSecurity Context 獲取當(dāng)前用戶信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Synchronized和ReentranLock的區(qū)別及說明
文章介紹了Java中的`synchronized`關(guān)鍵字和`ReentrantLock`類,兩者都可以用于解決多線程同步問題,但`ReentrantLock`提供了更多的功能和靈活性2024-12-12使用Lombok @Builder注解導(dǎo)致默認(rèn)值無效的問題
這篇文章主要介紹了使用Lombok @Builder注解導(dǎo)致默認(rèn)值無效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08java使用監(jiān)聽器實(shí)現(xiàn)一個(gè)統(tǒng)計(jì)網(wǎng)站在線人數(shù)的示例
本文主要介紹了java使用監(jiān)聽器實(shí)現(xiàn)一個(gè)統(tǒng)計(jì)網(wǎng)站在線人數(shù)的示例,具有一定的參考價(jià)值,有需要的朋友可以了解一下。2016-10-10Java Annotation注解相關(guān)原理代碼總結(jié)
這篇文章主要介紹了Java Annotation注解相關(guān)原理代碼總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07javascript與jsp發(fā)送請(qǐng)求到servlet的幾種方式實(shí)例
本文分別給出了javascript發(fā)送請(qǐng)求到servlet的5種方式實(shí)例與 jsp發(fā)送請(qǐng)求到servlet的6種方式實(shí)例2018-03-03