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

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

 更新時(shí)間:2025年04月27日 15:02:28   作者:axinawang  
這篇文章主要介紹了Spring Security自定義身份認(rèn)證的實(shí)現(xiàn)方法,下面對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)證。對于自定義用戶認(rèn)證,Spring Security提供了多種認(rèn)證方式,常用的有In-Memory Authentication(內(nèi)存身份認(rèn)證)、JDBC Authentication(JDBC身份認(rèn)證)和UserDetailsService(身份詳情服務(wù))。下面對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)注為過時(shí),推薦直接聲明配置類,在配置類中直接定義組件的信息。 本書使用Spring Boot 2.7.6,其對應(yīng)的Spring Security版本為5.7.5。自定義內(nèi)存身份認(rèn)證時(shí),可以通過InMemoryUserDetailsManager類實(shí)現(xiàn),InMemoryUserDetailsManager是UserDetailsService的一個(gè)實(shí)現(xiàn)類,方便在內(nèi)存中創(chuàng)建一個(gè)用戶。對此,只需 在自定義配置類中創(chuàng)建InMemoryUserDetailsManager實(shí)例,在該實(shí)例中指定該實(shí)例的認(rèn)證信息,并存入在Spring容器中即可。

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

創(chuàng)建一個(gè)配置類WebSecurityConfig,在該類中創(chuàng)建UserDetailsService類型的InMemoryUserDetailsManager實(shí)例對象交由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è)問題。

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

從Spring Security 5開始,自定義用戶認(rèn)證如果沒有設(shè)置密碼編碼器,也沒有在密碼前使用{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)沒有默認(rèn)安全管理時(shí)隨機(jī)生成了密碼。

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

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

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

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

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

#選擇使用數(shù)據(jù)庫
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ù)庫連接的相關(guān)配置信息

(4)修改配置類

修改WebSecurityConfig配置類userDetailsService()方法,將該方法創(chuàng)建的實(shí)例對象修改為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)效果測試

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

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

使用InMemoryUserDetailsManager和JdbcUserDetailsManager進(jìn)行身份認(rèn)證時(shí),其真正的認(rèn)證邏輯都在UserDetailsService接口重寫的loadUserByUsername()方法中。對于一個(gè)完善的項(xiàng)目來說,通常會(huì)實(shí)現(xiàn)用戶信息查詢服務(wù),對此可以自定義一個(gè)UserDetailsService實(shí)現(xiàn)類,重寫該接口的loadUserByUsername()方法,在該方法中查詢用戶信息,將查詢到的用戶信息填充到UserDetails對象返回,以實(shí)現(xiàn)用戶的身份認(rèn)證。下面通過案例對自定義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ù)庫查詢用戶
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ù)庫根據(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)效果測試

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

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

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

相關(guān)文章

最新評(píng)論

新源县| 岢岚县| 会理县| 金寨县| 梁平县| 榆林市| 荣昌县| 安新县| 平谷区| 建平县| 梁平县| 巴东县| 罗定市| 化隆| 卓尼县| 银川市| 卢湾区| 琼结县| 徐闻县| 富蕴县| 桓台县| 呼图壁县| 镇平县| 阿坝县| 沅陵县| 石河子市| 广州市| 桃园市| 金溪县| 喀喇沁旗| 应城市| 江孜县| 富川| 余干县| 房产| 托里县| 清河县| 南澳县| 雅江县| 台北县| 黔东|