關于SpringSecurity?Context?中獲取和更改當前用戶信息的問題
SpringSecurity Context 獲取和更改用戶信息的問題
SecurityContext 異步線程中獲取用戶信息
今天在做項目時遇到了一個問題,我需要獲取當前用戶的 ID。之前,前端并沒有存儲用戶信息,我一直是在后端的 service 中通過 SecurityContext 來獲取用戶信息,這個方法之前一直有效。然而,今天在另一個 service 中調(diào)用時卻無法獲取到用戶信息。
經(jīng)過詳細排查,發(fā)現(xiàn) SecurityContext 的內(nèi)容是與請求線程(如 HTTP 請求)綁定的。但我當前的 service 是用于處理 MQTT 消息,這屬于異步線程。因此,在異步線程中無法從 SecurityContext 獲取用戶信息,只能另尋解決方案。
/**
* 處理接收到的設備數(shù)據(jù),根據(jù)數(shù)據(jù)類型進行不同的處理。energy數(shù)據(jù)存儲到數(shù)據(jù)庫,其他數(shù)據(jù)通過WebSocket發(fā)送到前端展示。
* @param data 數(shù)據(jù)內(nèi)容
*/
private void handleIncomingData(String data) {
......
/*
* 通過設備ID找到用戶ID, 不能通過securityContext獲取當前用戶ID,因為這里是異步處理消息,不在請求線程中。
* 通過securityContext獲取當前用戶ID的方法只能在請求線程中使用,通常是與HTTP請求相關的操作才能獲取到。
* 這里是MQTT消息處理,不在請求線程中,所以要通過其他方式獲取當前用戶ID。
* 還因為這里是存入數(shù)據(jù)庫,因為也不能依賴物理設備的用戶ID,設備不一定是存用戶ID, 降低耦合性。
TODO: 這里是否可以改進?
*/
long userId = deviceMapper.findDeviceById(deviceId).getUserId();
if (userId<=0) {//如果userId<=0,說明沒有找到對應的設備
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 線程降級問題
在項目中遇到 SecurityContext 線程降級的問題,具體場景是用戶修改個人資料(如郵箱)后,我希望 SecurityContext 中的用戶信息能及時更新。然而,在修改郵箱后,用戶需要跳轉(zhuǎn)到郵箱驗證碼驗證頁面,該頁面通過 security 配置中的 permitAll() 允許匿名訪問。
這個配置導致一個問題:雖然用戶已經(jīng)登錄認證,但在訪問 /verify-code 頁面時,SecurityContext 中的身份會被降級為匿名用戶,進而導致更新后的信息沒有在 SecurityContext 中及時反映。
我了解到可以通過 setAuthentication() 手動更新 SecurityContext,但嘗試后依然無法解決問題,更新后的用戶信息仍舊無法及時同步到 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();
}到此這篇關于SpringSecurity Context 中 獲取 和 更改 當前用戶信息的問題的文章就介紹到這了,更多相關SpringSecurity Context 獲取當前用戶信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于Synchronized和ReentranLock的區(qū)別及說明
文章介紹了Java中的`synchronized`關鍵字和`ReentrantLock`類,兩者都可以用于解決多線程同步問題,但`ReentrantLock`提供了更多的功能和靈活性2024-12-12
java使用監(jiān)聽器實現(xiàn)一個統(tǒng)計網(wǎng)站在線人數(shù)的示例
本文主要介紹了java使用監(jiān)聽器實現(xiàn)一個統(tǒng)計網(wǎng)站在線人數(shù)的示例,具有一定的參考價值,有需要的朋友可以了解一下。2016-10-10
Java Annotation注解相關原理代碼總結(jié)
這篇文章主要介紹了Java Annotation注解相關原理代碼總結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07
javascript與jsp發(fā)送請求到servlet的幾種方式實例
本文分別給出了javascript發(fā)送請求到servlet的5種方式實例與 jsp發(fā)送請求到servlet的6種方式實例2018-03-03

