最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶(hù)

 更新時(shí)間:2023年01月04日 09:54:24   作者:bangiao  
這篇文章主要為大家介紹了Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶(hù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本章內(nèi)容

  • 如何從數(shù)據(jù)庫(kù)中讀取用戶(hù)對(duì)象
  • 源碼分析

如何從數(shù)據(jù)庫(kù)中讀取用戶(hù)對(duì)象?

1前面我們分析認(rèn)證的時(shí)候就會(huì)發(fā)現(xiàn)他在DaoAuthenticationProvider中就已經(jīng)有從數(shù)據(jù)庫(kù)中獲取用戶(hù)名和密碼的。

public interface UserDetailsService {
   UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

意思是說(shuō)我們只要重寫(xiě)這個(gè)類(lèi),就可以從我們所想要的地方獲取用戶(hù)信息。

那我們重寫(xiě)吧

public class MybatisUserDetailsService implements UserDetailsService, UserDetailsPasswordService {
	@Resource
	private UsersMapper usersMapper;
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		Users users = usersMapper.loadUserByUsername(username);
		if (null == users) {
			throw new UsernameNotFoundException(username);
		}
		return users;
	}
	@Override
	public UserDetails updatePassword(UserDetails user, String newPassword) {
		if (user instanceof Users users) {
			users.setPassword(newPassword);
			usersMapper.updateByPrimaryKeySelective(users);
		}
		return user;
	}
}

發(fā)現(xiàn)這里需要把spring security的users對(duì)象轉(zhuǎn)換成我們所需要的users對(duì)象。比較麻煩。

小白: "為什么不直接使用spring security那里面的users對(duì)象呢?"

小黑: "我們自己實(shí)現(xiàn)users對(duì)象的話(huà)就可以在自定義。特別是權(quán)限這邊,我們肯定是需要自定義users對(duì)象的,不能直接使用其內(nèi)部的對(duì)象。"

然后我們直接繼承UserDetails接口,然后自定義一些我們所需要的屬性。說(shuō)白了就是從內(nèi)置users對(duì)象中拷貝一些代碼出來(lái)。

小黑: "這里我故意留下了一個(gè)坑,如果你真的從內(nèi)置的users對(duì)象里的話(huà),你會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題。"

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Users implements Serializable, UserDetails {
    private Long id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean accountnonexpired;
    private Boolean accountnonlocked;
    private Boolean credentialsnonexpired;
    private List<Roles> rolesList;
    private static final long serialVersionUID = 1L;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Roles roles : getRolesList()) {
            authorities.add(new SimpleGrantedAuthority(roles.getRole()));
        }
        return authorities;
    }
    @Override
    public boolean isAccountNonExpired() {
        return accountnonexpired;
    }
    @Override
    public boolean isAccountNonLocked() {
        return accountnonlocked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsnonexpired;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

小白: "代碼定義好了,但現(xiàn)在你要怎么加入到spring security中呢?讓spring security主動(dòng)調(diào)用我們自定義的類(lèi)呢?"

小黑: "我們要使用自定義的類(lèi)的話(huà),無(wú)非是在DaoAuthenticationProvider里面設(shè)置。所以我們只要找到setUserDetailsService這個(gè)函數(shù)就行了。看一下有哪些方法調(diào)用了這個(gè)函數(shù)?"

看了一下發(fā)現(xiàn)這邊調(diào)用了setUserDetailsService方法的。前面的UserDetailsService是對(duì)象是通過(guò)spring bean上下文面拿出來(lái)的。

那我們也可以效仿他的方式,在spring bean上添加我們的UserDetailsService Bean。

@Bean
public UserDetailsService userDetailsService() {
   return new MybatisUserDetailsService();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
   return httpSecurity.authorizeHttpRequests()
         .anyRequest().authenticated()
         .and()
         .formLogin()
         .defaultSuccessUrl("/hello", true) // 認(rèn)證成功后訪問(wèn)
         .permitAll() // 白名單
         .and()
         .logout()
         .logoutUrl("/logout")
         .logoutSuccessUrl("/login") // 注銷(xiāo)成功后訪問(wèn)
         .clearAuthentication(true)
         .invalidateHttpSession(true)
         .and()
         .build();
}
@GetMapping("hello")
public HashMap<String, Object> hello(Authentication authentication) {
   HashMap<String, Object> map = new HashMap<>();
   Object principal = authentication.getPrincipal();
   String name = authentication.getName();
   map.put("principal", principal);
   map.put("name", name);
   return map;
}

小白: "停一下, 你數(shù)據(jù)庫(kù)表結(jié)構(gòu)呢? "

小黑: "我忘了, 我找找在哪可以抄"

在分析UserDetailsService的時(shí)候, 我們一般都要看看他的類(lèi)族是怎樣的, 結(jié)果發(fā)現(xiàn)可以偷懶的地方, 也就是表結(jié)構(gòu)的位置

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);
create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);

這段sql要改改, 否則mysql無(wú)法執(zhí)行

結(jié)果發(fā)現(xiàn), 就這...

我還不如自己設(shè)計(jì)呢

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for authorities
-- ----------------------------
DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities`  (
  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  UNIQUE INDEX `ix_auth_username`(`username` ASC, `authority` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `enabled` bit(1) NULL DEFAULT NULL,
  `accountNonExpired` bit(1) NULL DEFAULT b'1',
  `accountNonLocked` bit(1) NULL DEFAULT b'1',
  `credentialsNonExpired` bit(1) NULL DEFAULT b'1',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

注意, 這里僅僅只是為了玩耍, 而非企業(yè), 在企業(yè)中, 肯定不是這么設(shè)計(jì)的, 一般根據(jù) RBAC 設(shè)計(jì)

小白: "這樣就完成了?"

小黑: "完成了, 其他代碼都是mybatis生成的, 簡(jiǎn)單"

啟動(dòng), 訪問(wèn) 崩了

等下, spring security脫敏呢? 為什么這里可以輸出密碼?

分析源碼看看

脫敏為什么沒(méi)有生效?

通過(guò)源碼分析,脫敏應(yīng)該是認(rèn)證成功之后的事情

大概看了下源碼, ProviderManager有脫敏, 但是為什么不生效呢?

看這代碼的意思, 是要我們?cè)?Users 類(lèi)上多添加一個(gè)接口CredentialsContainer

public class Users implements Serializable, UserDetails, CredentialsContainer {
	@Override
	public void eraseCredentials() {
        // 設(shè)置 password 為 null
		this.password = null;
	}
}

行, 前面的坑補(bǔ)上了。再試試

完美~~~

總結(jié)

記住UserDetailsService怎么自定義, 注意自定義的User需要實(shí)現(xiàn)哪些接口, 還有脫敏問(wèn)題

以上就是詳解Spring Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶(hù)的詳細(xì)內(nèi)容,更多關(guān)于Spring Security數(shù)據(jù)庫(kù)加載用戶(hù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Idea使用插件實(shí)現(xiàn)逆向工程搭建SpringBoot項(xiàng)目的圖文教程

    Idea使用插件實(shí)現(xiàn)逆向工程搭建SpringBoot項(xiàng)目的圖文教程

    這篇文章主要介紹了Idea使用插件實(shí)現(xiàn)逆向工程搭建SpringBoot項(xiàng)目,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 詳解Java 10 var關(guān)鍵字和示例教程

    詳解Java 10 var關(guān)鍵字和示例教程

    在本文中,我將通過(guò)示例介紹新的Java SE 10特性——“var”類(lèi)型。你將學(xué)習(xí)如何在代碼中正確使用它,以及在什么情況下不能使用它,需要的朋友可以參考下
    2018-10-10
  • java中TreeMap集合的常用方法詳解

    java中TreeMap集合的常用方法詳解

    本篇文章給大家?guī)?lái)的內(nèi)容是關(guān)于java中TreeMap集合的常用方法詳解,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。下面我們就來(lái)學(xué)習(xí)一下吧
    2021-11-11
  • java中instanceof和getClass()的區(qū)別分析

    java中instanceof和getClass()的區(qū)別分析

    本篇文章介紹了,在java中instanceof和getClass()的區(qū)別分析。需要的朋友參考下
    2013-04-04
  • java中mybatis和hibernate的用法總結(jié)

    java中mybatis和hibernate的用法總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于java中mybatis和hibernate的用法總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-01-01
  • redis客戶(hù)端Jedis使用小結(jié)

    redis客戶(hù)端Jedis使用小結(jié)

    Jedis是Redis的一款Java語(yǔ)言的開(kāi)源客戶(hù)端連接工具,本文主要介紹了redis客戶(hù)端Jedis使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Springboot項(xiàng)目Mybatis升級(jí)為Mybatis-Plus的詳細(xì)步驟

    Springboot項(xiàng)目Mybatis升級(jí)為Mybatis-Plus的詳細(xì)步驟

    在許多 Java 項(xiàng)目中,MyBatis 是一個(gè)廣泛使用的 ORM 框架,然而,隨著 MyBatis-Plus 的出現(xiàn),許多開(kāi)發(fā)者開(kāi)始遷移到這個(gè)更加簡(jiǎn)潔、高效的工具,它在 MyBatis 的基礎(chǔ)上提供了更多的功能,所以本文將介紹Springboot項(xiàng)目Mybatis升級(jí)為Mybatis-Plus的詳細(xì)步驟
    2025-03-03
  • springboot集成mybatis官方生成器

    springboot集成mybatis官方生成器

    本文主要介紹了springboot集成mybatis官方生成器,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java使用ExecutorService來(lái)停止線(xiàn)程服務(wù)

    Java使用ExecutorService來(lái)停止線(xiàn)程服務(wù)

    這篇文章主要介紹了Java使用ExecutorService來(lái)停止線(xiàn)程服務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • maven項(xiàng)目打包如何去掉不需要的module

    maven項(xiàng)目打包如何去掉不需要的module

    文章總結(jié):在my-project工程依賴(lài)my-core和my-common,且my-project在總工程AAA中時(shí),建議通過(guò)以下兩種方案優(yōu)化打包流程:1.?使用pom區(qū)分,重新編寫(xiě)pom文件,并指定需要重新編譯的工程到modules中,然后在編譯時(shí)指定pom文件;
    2024-12-12

最新評(píng)論

华安县| 上犹县| 昭平县| 封开县| 封丘县| 印江| 阳泉市| 朝阳县| 丰都县| 高州市| 三门峡市| 防城港市| 元氏县| 澎湖县| 灵石县| 丽水市| 准格尔旗| 吐鲁番市| 沙雅县| 沾化县| 嘉峪关市| 沁水县| 吴旗县| 平武县| 彰化县| 卢氏县| 疏附县| 昔阳县| 临汾市| 乳山市| 塔城市| 滕州市| 乐业县| 瑞丽市| 亳州市| 威远县| 张家川| 江源县| 肥乡县| 哈巴河县| 沽源县|