網(wǎng)站首頁 編程語言 正文
前言
前置閱讀
spring boot security快速使用示例
spring boot security之前后端分離配置
說明
實際場景,我們一般是把用戶信息保存在db中(也可能是調(diào)用三方接口),需要自定義用戶信息加載或認(rèn)證部分的邏輯,下面提供一個示例。
代碼示例
定義用戶bean
@AllArgsConstructor
@Data
public class User {
private String username;
private String password;
}
定義Mapper
示例,代碼寫死了,并不是實際從數(shù)據(jù)庫或某個存儲查詢用戶信息:
@Component
public class UserMapper {
public User select(String username) {
return new User(username, "pass");
}
}
定義加載用戶數(shù)據(jù)的類
UserDetailsService 是spring security內(nèi)置的加載用戶信息的接口,我們只需要實現(xiàn)這個接口:
@Slf4j
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
public static final UserDetails INVALID_USER =
new org.springframework.security.core.userdetails.User("invalid_user", "invalid_password", Collections.emptyList());
private final UserMapper userMapper;
public UserDetailsServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 根據(jù)用戶名從數(shù)據(jù)庫查詢用戶信息
User user = userMapper.select(username);
if (user == null) {
/**
* 如果沒查詢到這個用戶,考慮兩種選擇:
* 1. 返回一個標(biāo)記無效用戶的常量對象
* 2. 返回一個不可能認(rèn)證通過的用戶
*/
return INVALID_USER;
// return new User(username, System.currentTimeMillis() + UUID.randomUUID().toString(), Collections.emptyList());
}
/**
* 這里返回的用戶密碼是否為庫里保存的密碼,是明文/密文,取決于認(rèn)證時密碼比對部分的實現(xiàn),每個人的場景不一樣,
* 因為使用的是不加密的PasswordEncoder,所以可以返回明文
*/
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), Collections.emptyList());
}
}
自定義認(rèn)證的bean配置
@Configuration
public class WebConfiguration {
@Bean
public PasswordEncoder passwordEncoder() {
// 示例,不對密碼進(jìn)行加密處理
return NoOpPasswordEncoder.getInstance();
}
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
// 設(shè)置加載用戶信息的類
provider.setUserDetailsService(userDetailsService);
// 比較用戶密碼的時候,密碼加密方式
provider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(Arrays.asList(provider));
}
}
注意,因為這個是示例,AuthenticationProvider使用的是spring security的DaoAuthenticationProvider ,在實際場景中,如果不滿足可以自定義實現(xiàn)或者繼承DaoAuthenticationProvider ,重寫其中的:additionalAuthenticationChecks方法,主要就是認(rèn)證檢查的,默認(rèn)實現(xiàn)如下:
@Override
@SuppressWarnings("deprecation")
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) {
this.logger.debug("Failed to authenticate since no credentials provided");
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
// 就是比對下請求傳過來的密碼和根據(jù)該用戶查詢的密碼是否一致,passwordEncoder是根據(jù)不同的加密算法進(jìn)行加密,示例我們用的是NoOpPasswordEncoder,也就是原始明文比對
if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
this.logger.debug("Failed to authenticate since password does not match stored value");
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
定義登錄接口
@RequestMapping("/login")
@RestController
public class LoginController {
private final AuthenticationManager authenticationManager;
public LoginController(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@PostMapping()
public Object login(@RequestBody User user) {
try {
// 使用定義的AuthenticationManager進(jìn)行認(rèn)證處理
Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
// 認(rèn)證通過,設(shè)置到當(dāng)前上下文,如果當(dāng)前認(rèn)證過程后續(xù)還有處理的邏輯需要的話。這個示例是沒有必要了
SecurityContextHolder.getContext().setAuthentication(authenticate);
return "login success";
}catch (Exception e) {
return "login failed";
}
}
/**
* 獲取驗證碼,需要的話,可以提供一個驗證碼獲取的接口,在上面的login里把驗證碼傳進(jìn)來進(jìn)行比對
*/
@GetMapping("/captcha")
public Object captcha() {
return "1234";
}
}
自定義HttpSecurity
@Component
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 在這里自定義配置
http.authorizeRequests()
// 登錄相關(guān)接口都允許訪問
.antMatchers("/login/**").permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
// 認(rèn)證失敗返回401狀態(tài)碼,前端頁面可以根據(jù)401狀態(tài)碼跳轉(zhuǎn)到登錄頁面
.authenticationEntryPoint((request, response, authException) ->
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase()))
.and().cors()
// csrf是否決定禁用,請自行考量
.and().csrf().disable()
// 采用http 的基本認(rèn)證.
.httpBasic();
}
}
測試
示例中,用戶密碼寫死是:pass,
用一個錯誤的密碼試一下,響應(yīng)登錄失敗:
使用正確的密碼,響應(yīng)登錄成功:
原文鏈接:https://blog.csdn.net/x763795151/article/details/131499404
- 上一篇:沒有了
- 下一篇:沒有了
相關(guān)推薦
- 2022-08-30 MongoDB數(shù)據(jù)庫基礎(chǔ)知識整理_MongoDB
- 2022-11-03 如何在C++類的外部調(diào)用類的私有方法_C 語言
- 2022-04-16 spyder快捷鍵與python符號化輸出方式_python
- 2022-04-25 Entity?Framework?Core中執(zhí)行SQL語句和存儲過程的方法介紹_實用技巧
- 2022-04-17 C語言中用棧+隊列實現(xiàn)隊列中的元素逆置_C 語言
- 2021-12-03 前端異常502?bad?gateway的原因和解決辦法_nginx
- 2022-04-01 ?python中pandas讀取csv文件?時如何省去csv.reader()操作指定列步驟_pyt
- 2022-10-31 理解k8s控制器DaemonSet創(chuàng)建及使用場景_云其它
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支