SpringSecurity認(rèn)證授權(quán)全流程解讀
SpringSecurity認(rèn)證流程:loadUserByUsername()方法內(nèi)部實(shí)現(xiàn)。
實(shí)現(xiàn)步驟
構(gòu)建一個自定義的service接口,實(shí)現(xiàn)SpringSecurity的UserDetailService接口。
建一個service實(shí)現(xiàn)類,實(shí)現(xiàn)此loadUserByUsername方法。
調(diào)用登錄的login接口,會經(jīng)過authenticationManager.authenticate(authenticationToken)方法。此方法會調(diào)用loadUserByUsername方法。
方法內(nèi)部做用戶信息的查詢,判斷用戶名和密碼是否正確,這是第一道認(rèn)證。
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final SysUserMapper sysUserMapper;
//用戶登錄請求/login,自動調(diào)用方法
//根據(jù)用戶名獲取用戶信息
//UserDetails 存儲用戶信息,包括用戶名,密碼,權(quán)限
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getUsername, username);
SysUser sysUser = sysUserMapper.selectOne(wrapper);
if (Objects.isNull(sysUser)){
throw new UsernameNotFoundException("用戶名不存在");
}
//認(rèn)證成功回UserDetails對象
return new LoginUser(sysUser);
}
}
@ToString
public class LoginUser implements UserDetails {
private SysUser sysUser;
public LoginUser(SysUser sysUser) {
this.sysUser = sysUser;
}
// 權(quán)限
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
}
@Override
public String getPassword() {
return sysUser.getPassword();
}
@Override
public String getUsername() {
return sysUser.getUsername();
}
// 賬號是否過期
@Override
public boolean isAccountNonExpired() {
return true;
}
// 賬號是否被鎖定
@Override
public boolean isAccountNonLocked() {
return true;
}
// 密碼是否過期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 賬號是否可用
@Override
public boolean isEnabled() {
return true;
}
}如果沒有查到信息就拋出異常。
如果查到信息了再接著查用戶的權(quán)限信息,返回權(quán)限信息到loginUser實(shí)體。
此實(shí)體實(shí)現(xiàn)了SpringSecurity自帶的userDetail接口。實(shí)現(xiàn)了getAuthorities方法。
每次查詢權(quán)限都會調(diào)用此方法。
查詢到的權(quán)限,會被返回到login接口。進(jìn)行后續(xù)操作。
如果認(rèn)證通過,通過身份信息中的userid生產(chǎn)一個jwt。
把完整的用戶信息作為value,token作為key存入redis。
@RestController
@Tag(name = "認(rèn)證模塊", description = "認(rèn)證模塊")
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
//注入AuthenticationManager(認(rèn)證管理器)
private final AuthenticationManager authenticationManager;
private final JwtUtils jwtUtils;
@PostMapping("/login")
@Operation(summary = "登錄")
public Result login(@RequestParam("username") String username, @RequestParam("password") String password) {
System.out.println(username + password);
//登錄邏輯
//調(diào)用UserDetailsService.loadUserByUsername方法獲取
//不能直接調(diào)用,需要通過AuthenticationManager進(jìn)行認(rèn)證
Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
Authentication authenticate = null;
try {
authenticate = authenticationManager.authenticate(authentication);
} catch (BadCredentialsException e) {
return Result.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR);
}
//認(rèn)證成功方法token
String token=jwtUtils.generateToken(authenticate);
return Result.success(token);
}
}
@Configuration
@EnableWebSecurity // 開啟web安全
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final IgnoredUrl ignoredUrl;
/**
* 配置認(rèn)證管理器 AuthenticationManager
* 作用:用于身份認(rèn)證
* 參數(shù):UserDetailsService, PasswordEncoder
*/
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(provider);
}
/**
* 密碼編碼器
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//關(guān)閉csrf防護(hù),否則回導(dǎo)致登錄失敗
http.csrf(a -> a.disable()); //禁用SCRF
//配置安全攔截規(guī)則
http.authorizeHttpRequests(req ->
req.requestMatchers(ignoredUrl.getUrls())
.permitAll()
.anyRequest().authenticated());
/**
* 配置登錄頁
*/
http.formLogin(form -> form
.loginPage("/")
.successForwardUrl("/index") //登錄成功跳轉(zhuǎn)頁面
.loginProcessingUrl("/login")//登錄處理url
.failureForwardUrl("/error") //登錄失敗跳轉(zhuǎn)頁面
// .usernameParameter("name")//自定義用戶名參數(shù)
// .passwordParameter("password")//自定義密碼參數(shù)
);
return http.build();
}
}@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Integer expiration;
/**
*
*/
public String generateToken(Authentication authentication) {
Date now = new Date();
Date expirationDate = DateUtil.offsetSecond(now, expiration);
Map<String, Object> claims = new HashMap<>();
claims.put("username", authentication.getName());//用戶名
claims.put("exp", expirationDate);
// claims.put();
return JWTUtil.createToken(claims, secret.getBytes());
}
}@Component
@Data
@ConfigurationProperties(prefix = "security.ignored")
@ToString
public class IgnoredUrl {
private String[] urls;
}
登錄成功

登陸失敗

總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用SpringBoot配置多數(shù)據(jù)源的經(jīng)驗(yàn)分享
這篇文章主要介紹了使用SpringBoot配置多數(shù)據(jù)源的經(jīng)驗(yàn)分享,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
Springboot整合SpringSecurity實(shí)現(xiàn)登錄認(rèn)證和鑒權(quán)全過程
這篇文章主要介紹了Springboot整合SpringSecurity實(shí)現(xiàn)登錄認(rèn)證和鑒權(quán)全過程,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Mybatis多條數(shù)據(jù)只返回一條的問題及解決
文章介紹了在MyBatis中進(jìn)行聯(lián)查時,如果只返回主表數(shù)據(jù)而子表數(shù)據(jù)相同,可能會導(dǎo)致重復(fù)數(shù)據(jù)的問題,解決方法是在主表對象中添加一個臨時字段,并將子表的不同數(shù)據(jù)封裝到主表中,從而避免重復(fù)數(shù)據(jù)的返回2026-03-03
解決struts2 攔截器修改request的parameters參數(shù)失敗的問題
這篇文章主要介紹了解決struts2 攔截器修改request的parameters參數(shù)失敗的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
Springboot-admin整合Quartz實(shí)現(xiàn)動態(tài)管理定時任務(wù)的過程詳解
Quartz是一款Java編寫的開源任務(wù)調(diào)度框架,同時它也是Spring默認(rèn)的任務(wù)調(diào)度框架,它的作用其實(shí)類似于Timer定時器以及ScheduledExecutorService調(diào)度線程池,這篇文章主要介紹了Springboot-admin整合Quartz實(shí)現(xiàn)動態(tài)管理定時任務(wù),需要的朋友可以參考下2023-04-04
性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解
這篇文章主要為大家介紹了性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03

