通過【從授權開始看源碼】我們可以看到這里主要就是干了幾件事情
- 通過filter 確定登錄要過濾的url
- 通過filter 確定生成的`AbstractAuthenticationToken` 比如 `UsernamePasswordAuthenticationToken`
- 通過生成的`AbstractAuthenticationToken` 確定`AuthenticationProvider`
- 通過`AuthenticationProvider` 最后調用 `authenticate()`方法最后進行授權
根據上面我們對自己對代碼進行了一些封裝
我們先來看`LoginAuthenticationFilter`
```java
public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationTokenParser authenticationTokenParser;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
AbstractAuthenticationToken authRequest = authenticationTokenParser.parse(requestBody);
return this.getAuthenticationManager().authenticate(authRequest);
}
public void setAuthenticationTokenParser(AuthenticationTokenParser authenticationTokenParser) {
this.authenticationTokenParser = authenticationTokenParser;
}
}
```
這里的登錄繼承了`UsernamePasswordAuthenticationFilter` 里面寫了
```java
public UsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/login", "POST"));
}
```
這就是為什么登錄的接口是`/login`的原因
我們再來看看生成`AbstractAuthenticationToken `的方法
`AbstractAuthenticationToken authRequest = authenticationTokenParser.parse(requestBody);`
這里決定了生成什么token,將會決定后面的`AuthenticationProvider`
我們先來看`AdminAuthenticationProvider`
```
@Override
public boolean supports(Class<?> authentication) {
return AdminAuthenticationToken.class.isAssignableFrom(authentication);
}
```
這里決定`AdminAuthenticationToken` 是通過`AdminAuthenticationProvider` 進行校驗
再來看下完整的`AdminAuthenticationProvider` 你就知道驗證碼在哪里校驗的了,是不是很簡單
```java
public class AdminAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private final YamiUserDetailsService yamiUserDetailsService;
private final PasswordEncoder passwordEncoder;
@Override
protected UserDetails retrieveUser(String username, Authentication authentication) throws BaseYamiAuth2Exception {
UserDetails user;
try {
user = yamiUserDetailsService.loadUserByUsername(username);
} catch (UsernameNotFoundExceptionBase var6) {
throw new UsernameNotFoundExceptionBase("賬號或密碼不正確");
}
if (!user.isEnabled()) {
throw new UsernameNotFoundExceptionBase("賬號已被鎖定,請聯系管理員");
}
return user;
}
@Override
protected void additionalAuthenticationChecks(UserDetails sysUser, Authentication authentication) throws BaseYamiAuth2Exception {
AdminAuthenticationToken adminAuthenticationToken = (AdminAuthenticationToken) authentication;
String kaptchaKey = SecurityConstants.SPRING_SECURITY_RESTFUL_IMAGE_CODE + adminAuthenticationToken.getSessionUUID();
String kaptcha = RedisUtil.get(kaptchaKey);
RedisUtil.del(kaptchaKey);
if(StrUtil.isBlank(adminAuthenticationToken.getImageCode()) || !adminAuthenticationToken.getImageCode().equalsIgnoreCase(kaptcha)){
throw new ImageCodeNotMatchExceptionBase("驗證碼有誤");
}
String encodedPassword = sysUser.getPassword();
String rawPassword = authentication.getCredentials().toString();
// 密碼不正確
if (!passwordEncoder.matches(rawPassword,encodedPassword)){
throw new BadCredentialsExceptionBase("賬號或密碼不正確");
}
}
@Override
protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
AdminAuthenticationToken result = new AdminAuthenticationToken(user, authentication.getCredentials());
result.setDetails(authentication.getDetails());
return result;
}
}
```
- 開發環境準備
- 基本開發手冊
- 項目目錄結構
- 權限管理
- 通用分頁表格
- Swagger文檔
- undertow容器
- 對xss攻擊的防御
- 分布式鎖
- 統一的系統日志
- 統一驗證
- 統一異常處理
- 文件上傳下載
- 一對多、多對多分頁
- 認證與授權
- 從授權開始看源碼
- 自己寫個授權的方法-開源版
- 商城表設計
- 商品信息
- 商品分組
- 購物車
- 訂單
- 地區管理
- 運費模板
- 接口設計
- 必讀
- 購物車的設計
- 訂單設計-確認訂單
- 訂單設計-提交訂單
- 訂單設計-支付
- 生產環境
- nginx安裝與跨域配置
- 安裝mysql
- 安裝redis
- 傳統方式部署項目
- docker
- 使用docker部署商城
- centos jdk安裝
- docker centos 安裝
- Docker Compose 安裝與卸載
- docker 鏡像的基本操作
- docker 容器的基本操作
- 通過yum安裝maven
- 常見問題