亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring Security自定義身份認(rèn)證的實(shí)現(xiàn)方法

 更新時(shí)間:2025年04月27日 15:02:28   作者:axinawang  
這篇文章主要介紹了Spring Security自定義身份認(rèn)證的實(shí)現(xiàn)方法,下面對(duì)Spring Security的這三種自定義身份認(rèn)證進(jìn)行詳細(xì)講解,需要的朋友可以參考下

盡管項(xiàng)目啟動(dòng)時(shí),Spring Security會(huì)提供了默認(rèn)的用戶信息,可以快速認(rèn)證和啟動(dòng),但大多數(shù)應(yīng)用程序都希望使用自定義的用戶認(rèn)證。對(duì)于自定義用戶認(rèn)證,Spring Security提供了多種認(rèn)證方式,常用的有In-Memory Authentication(內(nèi)存身份認(rèn)證)、JDBC Authentication(JDBC身份認(rèn)證)和UserDetailsService(身份詳情服務(wù))。下面對(duì)Spring Security的這三種自定義身份認(rèn)證進(jìn)行詳細(xì)講解。

1.內(nèi)存身份認(rèn)證

以內(nèi)存身份認(rèn)證時(shí),需要在Spring Security的相關(guān)組件中進(jìn)行指定當(dāng)前認(rèn)證方式為內(nèi)存身份認(rèn)證。Spring Security 5.7.1開始Spring Security將WebSecurityConfigurerAdapter類標(biāo)注為過(guò)時(shí),推薦直接聲明配置類,在配置類中直接定義組件的信息。 本書使用Spring Boot 2.7.6,其對(duì)應(yīng)的Spring Security版本為5.7.5。自定義內(nèi)存身份認(rèn)證時(shí),可以通過(guò)InMemoryUserDetailsManager類實(shí)現(xiàn),InMemoryUserDetailsManager是UserDetailsService的一個(gè)實(shí)現(xiàn)類,方便在內(nèi)存中創(chuàng)建一個(gè)用戶。對(duì)此,只需 在自定義配置類中創(chuàng)建InMemoryUserDetailsManager實(shí)例,在該實(shí)例中指定該實(shí)例的認(rèn)證信息,并存入在Spring容器中即可。

(1)創(chuàng)建配置類

創(chuàng)建一個(gè)配置類WebSecurityConfig,在該類中創(chuàng)建UserDetailsService類型的InMemoryUserDetailsManager實(shí)例對(duì)象交由Spring容器管理

@Configuration
public  class  WebSecurityConfig {
@Bean
public  UserDetailsService userDetailsService() {
InMemoryUserDetailsManager users = new  InMemoryUserDetailsManager();
users.createUser(User.withUsername("zhangsan")
.password("{noop}1234")
.roles("ADMIN")
.build());
return  users;
}
}

進(jìn)行自定義用戶認(rèn)證時(shí),需要注意以下幾個(gè)問(wèn)題。

提交認(rèn)證時(shí)會(huì)對(duì)輸入的密碼使用密碼編譯器進(jìn)行加密并與正確的密碼進(jìn)行校驗(yàn)。如果不想要對(duì)輸入的密碼進(jìn)行加密,需要在密碼前對(duì)使用{noop}進(jìn)行標(biāo)注。

從Spring Security 5開始,自定義用戶認(rèn)證如果沒(méi)有設(shè)置密碼編碼器,也沒(méi)有在密碼前使用{noop}進(jìn)行標(biāo)注,會(huì)認(rèn)證失敗。

自定義用戶認(rèn)證時(shí),可以定義用戶角色roles,也可以定義用戶權(quán)限authorities,在進(jìn)行賦值時(shí),權(quán)限通常是在角色值的基礎(chǔ)上添加“ROLE_”前綴。

自定義用戶認(rèn)證時(shí),可以為某個(gè)用戶一次指定多個(gè)角色或權(quán)限。

(2)驗(yàn)證內(nèi)存身份認(rèn)證

啟動(dòng)項(xiàng)目后,查看控制臺(tái)輸出的信息,發(fā)現(xiàn)沒(méi)有默認(rèn)安全管理時(shí)隨機(jī)生成了密碼。

在瀏覽器訪問(wèn)項(xiàng)目首頁(yè)“http://localhost:8080/”。

2.JDBC身份認(rèn)證

JDBC身份認(rèn)證是通過(guò)JDBC連接數(shù)據(jù)庫(kù),基于數(shù)據(jù)庫(kù)中已有的用戶信息進(jìn)行身份認(rèn)證,這樣避免了內(nèi)存身份認(rèn)證的弊端,可以實(shí)現(xiàn)對(duì)系統(tǒng)已注冊(cè)的用戶進(jìn)行身份認(rèn)證。JdbcUserDetailsManager是Spring Security內(nèi)置的UserDetailsService的實(shí)現(xiàn)類,使用JdbcUserDetailsManager可以通過(guò)JDBC將數(shù)據(jù)庫(kù)和Spring Security連接起來(lái)。下面對(duì)JDBC身份認(rèn)證方式進(jìn)行講解。

(1)數(shù)據(jù)準(zhǔn)備

使用之前創(chuàng)建的名為springbootdata的數(shù)據(jù)庫(kù),在該數(shù)據(jù)庫(kù)中創(chuàng)建三個(gè)表user、priv和user_priv,并預(yù)先插入幾條測(cè)試數(shù)據(jù)。準(zhǔn)備數(shù)據(jù)的SQL語(yǔ)句如下。 

#選擇使用數(shù)據(jù)庫(kù)
USEspringbootdata;
#創(chuàng)建表user并插入相關(guān)數(shù)據(jù)
DROPTABLEIFEXISTS`user`;
CREATETABLE`user`(
`id`int(20)NOTNULLAUTO_INCREMENT,
`username`varchar(200)DEFAULTNULL,
`password`varchar(200)DEFAULTNULL,
`valid`tinyint(1)NOTNULLDEFAULT1,
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=4DEFAULTCHARSET=utf8;
INSERTINTO`user`VALUES('1','zhangsan',
'$2a$10$7fWqX7Y010pMnyym/AHZX.3chIbnPZbj3N/iqcG4APCF.hC6CMh5a','1');
INSERTINTO`user`VALUES('2','lisi',
'$2a$10$7fWqX7Y010pMnyym/AHZX.3chIbnPZbj3N/iqcG4APCF.hC6CMh5a','1');
#創(chuàng)建表priv并插入相關(guān)數(shù)據(jù)
DROPTABLEIFEXISTS`priv`;
CREATETABLE`priv`(
`id`int(20)NOTNULLAUTO_INCREMENT,
`authority`varchar(20)DEFAULTNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=3DEFAULTCHARSET=utf8;
INSERTINTO`priv`VALUES('1','ROLE_COMMON');
INSERTINTO`priv`VALUES('2','ROLE_ADMIN');
#創(chuàng)建表user_priv并插入相關(guān)數(shù)據(jù)
DROPTABLEIFEXISTS`user_priv`;
CREATETABLE`user_priv`(
`id`int(20)NOTNULLAUTO_INCREMENT,
`user_id`int(20)DEFAULTNULL,
`priv_id`int(20)DEFAULTNULL,
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=5DEFAULTCHARSET=utf8;
INSERTINTO`user_priv`VALUES('1','1','1');
INSERTINTO`user_priv`VALUES('2','2','2');

 (2)配置依賴

添加JDBC的啟動(dòng)器依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

(3)設(shè)置配置信息

設(shè)置數(shù)據(jù)庫(kù)連接的相關(guān)配置信息

(4)修改配置類

修改WebSecurityConfig配置類userDetailsService()方法,將該方法創(chuàng)建的實(shí)例對(duì)象修改為JdbcUserDetailsManager

@Configuration
public  class  WebSecurityConfig {
@Autowired
private  DataSource dataSource;
@Bean
public  PasswordEncoder passwordEncoder() {
return  new  BCryptPasswordEncoder();
}
@Bean
public  UserDetailsService userDetailsService() {
String userSQL ="SELECT username,password, valid " +
"FROM user WHERE username = ?";
String authoritySQL="SELECT u.username,p.authority " +
"FROM user u,priv p,user_priv up " +
"WHERE up.user_id=u.id AND up.priv_id=p.id and u.username =?";
JdbcUserDetailsManager users = new  JdbcUserDetailsManager();
users.setDataSource(dataSource);
users.setUsersByUsernameQuery(userSQL);
users.setAuthoritiesByUsernameQuery(authoritySQL);
return  users;
}
}

(5)效果測(cè)試

重啟項(xiàng)目進(jìn)行效果測(cè)試

3.自定義UserDetailsService身份認(rèn)證

使用InMemoryUserDetailsManager和JdbcUserDetailsManager進(jìn)行身份認(rèn)證時(shí),其真正的認(rèn)證邏輯都在UserDetailsService接口重寫的loadUserByUsername()方法中。對(duì)于一個(gè)完善的項(xiàng)目來(lái)說(shuō),通常會(huì)實(shí)現(xiàn)用戶信息查詢服務(wù),對(duì)此可以自定義一個(gè)UserDetailsService實(shí)現(xiàn)類,重寫該接口的loadUserByUsername()方法,在該方法中查詢用戶信息,將查詢到的用戶信息填充到UserDetails對(duì)象返回,以實(shí)現(xiàn)用戶的身份認(rèn)證。下面通過(guò)案例對(duì)自定義UserDetailsService進(jìn)行身份驗(yàn)證的實(shí)現(xiàn)進(jìn)行演示 。

(1)創(chuàng)建實(shí)體類

在子包entity下創(chuàng)建用戶實(shí)體類UserDto和權(quán)限實(shí)體類Privilege

public  class  UserDto {
private  Integer id; //用戶編號(hào)
private  String username; //用戶名稱
private  String password; //密碼
private  Integer valid; //是否合法
public  Integer getId() {
return  id;
}
public  void  setId(Integer id) {
this .id = id;
}
public  String getUsername() {
return  username;
}
public  void  setUsername(String username) {
this .username = username;
}
public  String getPassword() {
return  password;
}
public  void  setPassword(String password) {
this .password = password;
}
public  Integer getValid() {
return  valid;
}
public  void  setValid(Integer valid) {
this .valid = valid;
}
}
public  class  Privilege {
private  Integer id; //編號(hào)
private  String authority; //權(quán)限
public  Integer getId() {
return  id;
}
public  void  setId(Integer id) {
this .id = id;
}
public  String getAuthority() {
return  authority;
}
public  void  setAuthority(String authority) {
this .authority = authority;
}
}

 (2)創(chuàng)建用戶持久層接口

在dao子包下創(chuàng)建用戶持久層接口,在接口中定義查詢用戶及角色信息的方法

@Repository
public  class  UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
//根據(jù)賬號(hào)查詢用戶信息
public  UserDto getUserByUsername(String username){
String sql = "SELECT * FROM user WHERE username = ?";
//連接數(shù)據(jù)庫(kù)查詢用戶
List<UserDto> list = jdbcTemplate.query(sql, new  BeanPropertyRowMapper<>(UserDto.class ),username);
if (list !=null && list.size()==1){
return  list.get(0);
}
return  null;
}
//根據(jù)用戶id查詢用戶權(quán)限
public  List<String> findPrivilegesByUserId(Integer userId){
String sql = "SELECT u.username,p.authority " +
"FROM user u,priv p,user_priv up " +
"WHERE up.user_id=u.id AND up.priv_id=p.id and u.id =?";
List<Privilege> list = jdbcTemplate.query(sql, new  BeanPropertyRowMapper<>(Privilege.class ), userId);
List<String> privileges = new  ArrayList<>();
list.forEach(p -> privileges.add(p.getAuthority()));
return  privileges;
}
}

(3)封裝用戶認(rèn)證信息

在service子包下創(chuàng)建UserDetailsServiceImpl類,該類實(shí)現(xiàn)UserDetailsService接口,并在重寫的loadUserByUsername()方法中封裝用戶認(rèn)證信息

@Service
public  class  UserDetailsServiceImpl implements  UserDetailsService {
@Autowired
UserDao userDao;
//根據(jù)用戶名查詢用戶信息
@Override
public  UserDetails loadUserByUsername(String username) throws  UsernameNotFoundException {
//連接數(shù)據(jù)庫(kù)根據(jù)賬號(hào)查詢用戶信息
UserDto userDto = userDao.getUserByUsername(username);
if (userDto == null){
//如果用戶查不到,返回null,會(huì)拋出異常
return  null;
}
//根據(jù)用戶的id查詢用戶的權(quán)限
List<String> privileges = userDao.findPrivilegesByUserId(userDto.getId());
//將privileges轉(zhuǎn)成數(shù)組
String[] privilegeArray = new  String[privileges.size()];
privileges.toArray(privilegeArray);
UserDetails userDetails = User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(privilegeArray).build();
return  userDetails;
}
}

(4)效果測(cè)試

將userDetailsService()方法進(jìn)行注釋,使用自定義UserDetailsService身份認(rèn)證。

重啟項(xiàng)目進(jìn)行效果測(cè)試。

到此這篇關(guān)于Spring Security自定義身份認(rèn)證的文章就介紹到這了,更多相關(guān)Spring Security自定義身份認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java多線程文件下載器的實(shí)現(xiàn)

    java多線程文件下載器的實(shí)現(xiàn)

    本文主要介紹了java多線程文件下載器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • Java如何讀取jar包中的resource資源文件

    Java如何讀取jar包中的resource資源文件

    這篇文章主要介紹了Java如何讀取jar包中的resource資源文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Springboot中@ConfigurationProperties輕松管理應(yīng)用程序的配置信息詳解

    Springboot中@ConfigurationProperties輕松管理應(yīng)用程序的配置信息詳解

    通過(guò)@ConfigurationProperties注解,可以將外部配置文件中的屬性值注入到JavaBean中,簡(jiǎn)化了配置屬性的讀取和管理,這使得SpringBoot應(yīng)用程序中配置文件的屬性值可以映射到POJO類中,實(shí)現(xiàn)類型安全的屬性訪問(wèn),此方法避免了手動(dòng)讀取配置文件屬性的需要
    2024-10-10
  • Java8如何構(gòu)建一個(gè)Stream示例詳解

    Java8如何構(gòu)建一個(gè)Stream示例詳解

    Java 8 是迄今為止在語(yǔ)義上改動(dòng)上最大的一個(gè)平臺(tái)。下面這篇文章主要給大家介紹了關(guān)于Java8如何構(gòu)建一個(gè)Stream的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04
  • 區(qū)塊鏈java代碼實(shí)現(xiàn)

    區(qū)塊鏈java代碼實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了區(qū)塊鏈java代碼實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)

    java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)

    這篇文章主要介紹了java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • IDEA在Maven項(xiàng)目中使用本地jar包的方法

    IDEA在Maven項(xiàng)目中使用本地jar包的方法

    我們?cè)谀玫脚f項(xiàng)目的時(shí)候,經(jīng)常會(huì)遇到一種情況,就是這個(gè)項(xiàng)目的maven中依賴了一個(gè)本地的jar包,這種情況就需要引入這個(gè)jar包,所以本文給大家介紹了IDEA在Maven項(xiàng)目中使用本地jar包的方法,需要的朋友可以參考下
    2024-04-04
  • SpringBoot解析指定Yaml配置文件的實(shí)現(xiàn)過(guò)程

    SpringBoot解析指定Yaml配置文件的實(shí)現(xiàn)過(guò)程

    這篇文章主要介紹了SpringBoot解析指定Yaml配置文件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • Java中String、StringBuffer和StringBuilder的區(qū)別與使用場(chǎng)景

    Java中String、StringBuffer和StringBuilder的區(qū)別與使用場(chǎng)景

    在Java編程中,String、StringBuffer和StringBuilder是用于處理字符串的常見類,它們?cè)诳勺冃浴⒕€程安全性和性能方面有所不同,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • java arrayList遍歷的四種方法及Java中ArrayList類的用法

    java arrayList遍歷的四種方法及Java中ArrayList類的用法

    arraylist是動(dòng)態(tài)數(shù)組,它具有三個(gè)好處分別是:動(dòng)態(tài)的增加和減少元素 、實(shí)現(xiàn)了ICollection和IList接口、靈活的設(shè)置數(shù)組的大小,本文給大家介紹java arraylist遍歷及Java arraylist 用法,感興趣的朋友一起學(xué)習(xí)吧
    2015-11-11

最新評(píng)論