springboot如何獲取登錄用戶的個(gè)人信息
在Spring Boot中,獲取登錄用戶的個(gè)人信息通常需要使用Spring Security框架來進(jìn)行身份認(rèn)證和授權(quán)。Spring Security提供了一個(gè)名為SecurityContextHolder的上下文對(duì)象,它包含了當(dāng)前請(qǐng)求的身份認(rèn)證信息。通過SecurityContextHolder,可以訪問當(dāng)前已認(rèn)證的用戶的信息。
1.Pojo實(shí)體類
當(dāng)使用 Spring Boot + Spring Security 構(gòu)建 Web 應(yīng)用程序時(shí),我們需要定義用戶實(shí)體類來存儲(chǔ)用戶信息。以下是一個(gè)基本的 User
實(shí)體類
@Entity @Table(name = "users") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column(nullable = false) private String password; @Column(nullable = false) private String fullName; @Column(nullable = false, unique = true) private String email; // 用戶角色定義為一個(gè)字符串,用逗號(hào)分隔 @Column(nullable = false) private String roles; // 其他字段和方法 // UserDetails 方法的實(shí)現(xiàn) @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Arrays.stream(roles.split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
在這個(gè)例子中,User
實(shí)體類使用 @Entity
和 @Table
注解進(jìn)行了標(biāo)記,表明它是一個(gè) JPA 實(shí)體類,并且對(duì)應(yīng)了一個(gè)名為 users
的數(shù)據(jù)庫(kù)表。實(shí)體類中包含了一些基本的屬性,例如 id
、username
、password
、fullName
和 email
。另外,roles
屬性定義了用戶的角色,這是一個(gè)字符串,多個(gè)角色之間用逗號(hào)分隔。
User
實(shí)體類實(shí)現(xiàn)了 UserDetails
接口,該接口包含了一些必須實(shí)現(xiàn)的方法,用于獲取用戶的授權(quán)信息。在 getAuthorities()
方法中,我們將用戶的角色字符串分割成多個(gè)角色,并將其轉(zhuǎn)換為 Spring Security 中的 GrantedAuthority
對(duì)象。其余的方法返回的都是 true
,表示這些限制條件都沒有被啟用。
你還可以根據(jù)你的業(yè)務(wù)需求對(duì) User
實(shí)體類進(jìn)行擴(kuò)展或修改。
要獲取已認(rèn)證用戶的信息,可以在控制器方法中注入Authentication對(duì)象,然后從該對(duì)象中獲取用戶信息。例如:
2. Controller層
import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/me") public UserDetails getUserDetails(Authentication authentication) { return (UserDetails) authentication.getPrincipal(); } }
在上面的代碼中,使用@GetMapping注解將控制器方法映射到“/me”路徑。方法中注入Authentication對(duì)象,并從該對(duì)象中獲取Principal,即已認(rèn)證用戶的信息。由于Spring Security默認(rèn)使用UserDetailsService來加載用戶信息,因此Principal通常是UserDetails對(duì)象。
如果您想要訪問更多的用戶信息,可以自定義一個(gè)UserDetailsService,通過UserDetailsService從數(shù)據(jù)庫(kù)或其他數(shù)據(jù)源中加載用戶信息。然后,您可以通過從Principal中獲取用戶名或其他標(biāo)識(shí)符來檢索用戶信息。
當(dāng)使用Spring Security進(jìn)行身份認(rèn)證時(shí),需要實(shí)現(xiàn)UserDetailsService接口來加載用戶信息。UserDetailsService接口只有一個(gè)方法:loadUserByUsername,該方法返回一個(gè)實(shí)現(xiàn)了UserDetails接口的對(duì)象,該對(duì)象包含有關(guān)用戶的信息。
下面是一個(gè)簡(jiǎn)單的UserDetailsService類的示例,它從內(nèi)存中的用戶列表中加載用戶信息:
3. Service層
import java.util.ArrayList; import java.util.List; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; public class MyUserDetailsService implements UserDetailsService { private List<User> users = new ArrayList<>(); public MyUserDetailsService() { users.add(new User("user1", "password1", getAuthorityList("ROLE_USER"))); users.add(new User("user2", "password2", getAuthorityList("ROLE_USER"))); users.add(new User("admin", "password", getAuthorityList("ROLE_USER", "ROLE_ADMIN"))); } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { for (User user : users) { if (user.getUsername().equals(username)) { return user; } } throw new UsernameNotFoundException("User not found with username: " + username); } private List<GrantedAuthority> getAuthorityList(String... roles) { List<GrantedAuthority> authorityList = new ArrayList<>(); for (String role : roles) { authorityList.add(new SimpleGrantedAuthority(role)); } return authorityList; } }
在上面的代碼中,MyUserDetailsService類實(shí)現(xiàn)了UserDetailsService接口,并重寫了loadUserByUsername方法。該方法首先檢查用戶列表中是否存在與傳遞的用戶名匹配的用戶,如果找到該用戶,則將其作為UserDetails對(duì)象返回。否則,拋出UsernameNotFoundException異常。
4. Spring Security配置類
在這個(gè)例子中,用戶列表是硬編碼在MyUserDetailsService類中的。在實(shí)際應(yīng)用中,您將從數(shù)據(jù)庫(kù)或其他數(shù)據(jù)源中獲取用戶信息,并在loadUserByUsername方法中使用它。此外,您還可以根據(jù)需要添加更多的用戶屬性,例如電子郵件地址、電話號(hào)碼等。
最后,值得一提的是,在實(shí)現(xiàn)UserDetailsService接口時(shí),請(qǐng)務(wù)必確保密碼已被加密并保存為哈希值。在本示例中,密碼是明文存儲(chǔ)的,但在實(shí)際應(yīng)用中,應(yīng)使用Spring Security提供的密碼編碼器來對(duì)密碼進(jìn)行加密。
以下是一份完整的示例代碼,包括一個(gè)自定義的UserDetailsService和Spring Security配置類:
import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("ADMIN", "USER") .antMatchers("/").permitAll() .and().formLogin() .and().logout().logoutSuccessUrl("/login").permitAll(); } } class MyUserDetailsService implements UserDetailsService { private List<User> users = new ArrayList<>(); public MyUserDetailsService() { users.add(new User("user1", "$2a$10$HKV7WJB/FNH8/3wXXtGB0.bDrxPlheBlsHSDkOizQ94RyL5v5n5oy", getAuthorityList("ROLE_USER"))); users.add(new User("user2", "$2a$10$L9.Jir1vH6Wjtr8ZnI6FseV6rHdLWnV7yI0g1lV7vLmFFopW8VzU6", getAuthorityList("ROLE_USER"))); users.add(new User("admin", "$2a$10$5aJN5O5pyrgQMDR.Ta5/0.hxOeSw/3nm3q9XcVvBIzDdtyA8DPZ3C", getAuthorityList("ROLE_USER", "ROLE_ADMIN"))); } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { for (User user : users) { if (user.getUsername().equals(username)) { return user; } } throw new UsernameNotFoundException("User not found with username: " + username); } private List<GrantedAuthority> getAuthorityList(String... roles) { List<GrantedAuthority> authorityList = new ArrayList<>(); for (String role : roles) { authorityList.add(new SimpleGrantedAuthority(role)); } return authorityList; } }
上面的代碼包含了一個(gè)自定義的UserDetailsService實(shí)現(xiàn)類和一個(gè)Spring Security配置類。以下是代碼中的一些要點(diǎn):
5. 測(cè)試注意事項(xiàng)
MyUserDetailsService類:這是一個(gè)自定義的UserDetailsService實(shí)現(xiàn)類,用于從硬編碼的用戶列表中加載用戶信息。在loadUserByUsername方法中,根據(jù)傳遞的用戶名
以下是使用Postman測(cè)試API接口的步驟:
- 打開Postman軟件并創(chuàng)建一個(gè)新的請(qǐng)求。在請(qǐng)求的URL地址欄中輸入API接口的URL,例如
http://localhost:8080/user/info
- 點(diǎn)擊請(qǐng)求方式旁邊的下拉菜單,選擇HTTP請(qǐng)求方法,例如GET方法。
- 在請(qǐng)求頭(Headers)中添加必要的認(rèn)證信息,例如添加一個(gè)Authorization頭,其值為Bearer加上訪問令牌(access token),例如
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMSIsInJvbGUiOiJVU0VSIiwiaWF0IjoxNTE2MjM5MDIyfQ.kNqr5ZCw5vFh1dW8Kq3t_ZL-3q_kh12VTWg_w8mZisI
- 如果API接口需要傳遞請(qǐng)求參數(shù),可以在請(qǐng)求參數(shù)(Params)中添加參數(shù)名和參數(shù)值。
- 點(diǎn)擊發(fā)送按鈕,發(fā)送請(qǐng)求并查看響應(yīng)結(jié)果。
- 如果請(qǐng)求成功,可以在響應(yīng)結(jié)果中看到API接口返回的數(shù)據(jù),如果請(qǐng)求失敗,可以查看響應(yīng)狀態(tài)碼和錯(cuò)誤信息來定位問題。
需要注意的是,在測(cè)試API接口時(shí),需要了解API接口的請(qǐng)求參數(shù)、請(qǐng)求方式、認(rèn)證方式等信息,并在請(qǐng)求頭和請(qǐng)求參數(shù)中正確傳遞信息。另外,為了避免誤操作,建議在測(cè)試環(huán)境中測(cè)試API接口,不要在生產(chǎn)環(huán)境中測(cè)試API接口
根據(jù)上面提供的代碼,如果在Postman中成功請(qǐng)求 /user/info
接口,將會(huì)收到類似下面的 JSON 格式響應(yīng)數(shù)據(jù):
{ "id": 1, "username": "user1", "fullName": "User One", "email": "user1@example.com" }
其中,id
是用戶ID,username
是用戶名,fullName
是用戶的全名,email
是用戶的電子郵件地址。這些數(shù)據(jù)是在 UserInfo
類中定義的。
需要注意的是,如果沒有授權(quán)訪問該接口或者用戶不存在,那么響應(yīng)數(shù)據(jù)中將不會(huì)包含這些信息。如果出現(xiàn)這種情況,響應(yīng)數(shù)據(jù)中可能會(huì)包含錯(cuò)誤消息。
6. Controller層代碼改造
當(dāng)使用 Spring Boot + Spring Security 構(gòu)建 Web 應(yīng)用程序時(shí),可以使用 ResponseEntity
類來設(shè)置響應(yīng)的 HTTP 狀態(tài)碼。ResponseEntity
類包裝了 HTTP 響應(yīng)的正文、HTTP 狀態(tài)碼以及響應(yīng)頭信息。它允許我們返回自定義響應(yīng)實(shí)體,而不是使用默認(rèn)的響應(yīng)實(shí)體。
在你的代碼中,你可以使用 ResponseEntity<UserInfo>
替換原本的 UserInfo
返回類型。這樣,就可以將 HTTP 狀態(tài)碼作為 ResponseEntity
的一部分返回到客戶端。在 getUserInfo()
方法中,你可以使用以下代碼返回帶有狀態(tài)碼的響應(yīng):
@GetMapping("/user/info") public ResponseEntity<UserInfo> getUserInfo() { // 獲取當(dāng)前登錄用戶 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } // 獲取用戶信息并返回 String username = authentication.getName(); UserInfo userInfo = userService.getUserInfoByUsername(username); return ResponseEntity.ok(userInfo); }
在這個(gè)例子中,如果用戶未授權(quán)或未經(jīng)身份驗(yàn)證,則將返回 HTTP 401 狀態(tài)碼。如果用戶已經(jīng)經(jīng)過身份驗(yàn)證,將返回 HTTP 200 狀態(tài)碼,并帶有用戶信息。
如果需要在 Postman 中測(cè)試 API 的響應(yīng)狀態(tài)碼,可以在請(qǐng)求完成后查看響應(yīng)面板的右上角,顯示的是響應(yīng)的狀態(tài)碼和消息。
在我上面已經(jīng)回答針對(duì)如何使用 ResponseEntity
設(shè)置 HTTP 狀態(tài)碼做了說明,同時(shí)也提到了如何在 Postman 中查看響應(yīng)的狀態(tài)碼。
在 Spring Boot 應(yīng)用程序中,我們可以使用 ResponseEntity
類來包裝響應(yīng)實(shí)體,并指定返回的 HTTP 狀態(tài)碼。例如,在 getUserInfo()
方法中,我們可以使用以下代碼返回帶有
@GetMapping("/user/info") public ResponseEntity<UserInfo> getUserInfo() { // 獲取當(dāng)前登錄用戶 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } // 獲取用戶信息并返回 String username = authentication.getName(); UserInfo userInfo = userService.getUserInfoByUsername(username); return ResponseEntity.ok(userInfo); }
在這個(gè)例子中,如果用戶未授權(quán)或未經(jīng)身份驗(yàn)證,則將返回 HTTP 401 狀態(tài)碼。如果用戶已經(jīng)經(jīng)過身份驗(yàn)證,將返回 HTTP 200 狀態(tài)碼,并帶有用戶信息。
在 Postman 中查看響應(yīng)的狀態(tài)碼,可以在請(qǐng)求完成后查看響應(yīng)面板的右上角,顯示的是響應(yīng)的狀態(tài)碼和消息。如果返回的狀態(tài)碼為200,則表示請(qǐng)求成功,其他狀態(tài)碼則表示請(qǐng)求失敗。
7. sql腳本
CREATE TABLE `users` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `password` VARCHAR(100) NOT NULL, `full_name` VARCHAR(100) NOT NULL, `email` VARCHAR(100) NOT NULL, `roles` VARCHAR(100) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `UK_username` (`username`), UNIQUE KEY `UK_email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
在這個(gè)例子中,我們定義了一個(gè)名為 users
的表,它包含了以下字段:
id
:用戶的唯一標(biāo)識(shí)符,使用自增長(zhǎng)的方式生成。username
:用戶的登錄名,必須是唯一的。password
:用戶的登錄密碼,存儲(chǔ)加密后的密碼。full_name
:用戶的全名,用于顯示用戶的真實(shí)姓名。email
:用戶的電子郵件地址,必須是唯一的。roles
:用戶的角色,以逗號(hào)分隔多個(gè)角色。
在實(shí)際應(yīng)用中,你可以根據(jù)需要對(duì)數(shù)據(jù)表進(jìn)行修改和擴(kuò)展。
到此這篇關(guān)于springboot獲取登錄用戶的個(gè)人信息的文章就介紹到這了,更多相關(guān)springboot登錄用戶的個(gè)人信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot結(jié)合JWT實(shí)現(xiàn)用戶登錄、注冊(cè)、鑒權(quán)
- 基于SpringBoot和Vue3的博客平臺(tái)的用戶注冊(cè)與登錄功能實(shí)現(xiàn)
- 啟用springboot security后登錄web頁(yè)面需要用戶名和密碼的解決方法
- SpringBoot登錄用戶權(quán)限攔截器
- springboot+thymeleaf+druid+mybatis 多模塊實(shí)現(xiàn)用戶登錄功能
- SpringBoot整合SpringSecurity和JWT的示例
- Springboot+Shiro記錄用戶登錄信息并獲取當(dāng)前登錄用戶信息的實(shí)現(xiàn)代碼
相關(guān)文章
Java如何優(yōu)雅地避免空指針異常(NullPointerException)
這篇文章主要給大家介紹了關(guān)于Java如何優(yōu)雅地避免空指針異常(NullPointerException)的相關(guān)資料,空指針異常(NullPointerException)是一種常見的運(yùn)行時(shí)異常,它在Java編程中經(jīng)常出現(xiàn),需要的朋友可以參考下2024-03-03Java讀文件修改默認(rèn)換行符的實(shí)現(xiàn)
這篇文章主要介紹了Java讀文件修改默認(rèn)換行符的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java實(shí)現(xiàn)五子棋的基礎(chǔ)方法
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)五子棋的基礎(chǔ)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09簡(jiǎn)單談?wù)凧ava遍歷樹深度優(yōu)先和廣度優(yōu)先的操作方式
這篇文章主要介紹了簡(jiǎn)單談?wù)凧ava遍歷樹深度優(yōu)先和廣度優(yōu)先的操作方式的相關(guān)資料,需要的朋友可以參考下2023-03-03Eclipse如何導(dǎo)入Maven項(xiàng)目詳解(新手初學(xué))
這篇文章主要介紹了Eclipse如何導(dǎo)入Maven項(xiàng)目詳解(新手初學(xué)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源,結(jié)合實(shí)例形式分析了Spring使用ClassPathResource加載xml資源的具體實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2019-12-12