diff --git a/spring/Spring Security/Spring Security.md b/spring/Spring Security/Spring Security.md
index 9ccc5f4..15b4252 100644
--- a/spring/Spring Security/Spring Security.md
+++ b/spring/Spring Security/Spring Security.md
@@ -38,6 +38,10 @@
- [将token持久化到数据库中](#将token持久化到数据库中)
- [RememberMe的接口及其实现](#rememberme的接口及其实现)
- [TokenBasedRememberMeService](#tokenbasedremembermeservice)
+ - [匿名身份认证](#匿名身份认证)
+ - [匿名认证配置](#匿名认证配置)
+ - [处理logout](#处理logout)
+ - [自定义登出url](#自定义登出url)
# Spring Security
@@ -732,5 +736,83 @@ RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
return rememberMeAuthenticationProvider;
}
```
+## 匿名身份认证
+Spring Security中,采用了`deny-by-default`策略,用以适配如下场景:除少数资源外(如homepage、login页面等),访问其他所有的资源都需要进行身份认证。
+
+Spring Security提供了匿名身份认证,对于“匿名身份认证”的用户,其实际和未经认证的用户没有任何区别。匿名认证只是为配置访问控制属性提供了更加便捷的方式,在匿名认证时,即使当前`SecurityContextHolder`中存在`anonymous authentication`对象,在调用一些servlet api例如`getCallerPrincipal`方法时,方法仍然会返回null。
+
+在使用anonymous authentication时,Spring Security的SecurityContextHolder一定含有Authentication对象,即使用户未经认证,Authentication对象也不可能为空。
+
+### 匿名认证配置
+匿名认证在Spring Security中是默认被提供的,可以对其进行自定义或者关闭。
+
+为了提供匿名认证特性,需要存在如下三个类:`AnonymousAuthenticationToken`、`AnonymousAuthenticationProvider`、`AnonymousAuthenticationFilter`。
+- `AnonymousAuthenticationToken`:该类是`Authentication`的实现类,并且存储了该匿名实体所拥有的权限`GrantedAuthority`
+- `AnonymousAuthenticationProvider`:该类被整合到`ProviderManager`的provider链中,故而`AnonymousAuthenticationToken`可以被支持进行处理
+- `AnonymousAuthenticationFilter`:该filter被嵌入到常规的认证机制之后,如果在执行到该filter时,当前SecurityContextHolder中不存在Authentication,那么其会自动将`AnonymousAuthenticationToken`加入到SecurityContextHolder中。
+
+定义filter和provider的方式如下所示,filter和provider共享相同的key,故而filter创建的token可以被provider接收:
+```java
+
+
+
+
+
+
+
+
+```
+
+`userAttribute`属性值,其格式为`usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]`。
+
+
+## 处理logout
+如果当前项目的类路径中包含`spring-boot-starter-security`依赖,那么spring security会自动加入logout支持,针对`GET`和`POST`的`/logout`请求都会响应。
+
+当通过get方式请求/logout时,spring security将展示一个登出页面。但如果csrf保护被关闭,那么不会展示登出确认页面,而是直接关闭。
+
+当请求/logout时,将通过一系列logoutHandler来实现如下逻辑:
+1. 将http session标记为失效(SecurityContextLogoutHandler)
+2. 清空SecurityContextHolderStrategy (SecurityContextLogoutHandler)
+3. 清空SecurityContextRepository(SecurityContextLogoutHandler)
+4. 清空所有rememberMe authentication(TokenRememberMeServices / PersistentTokenRememberMeServices)
+5. 清空任何csrf token (LogoutSuccessEventPublishingLogoutHandler)
+6. 发送LogoutSuccessEvent(LogoutSuccessEventPublishingLogoutHandler)
+
+### 自定义登出url
+在filter chain中,logoutFilter位于AuthorizationFilter之前,故而没有必要显式的对/logout url执行permit操作(因为尚未执行到AuthorizationFilter之前,就会通过logoutFilter执行登出操作)。
+
+但是,对于自定义的登出端口(默认情况下,logooutFilter只对/logout的请求进行处理),若url不为/logout,那么需要调用`permitAll`来让自定义登出端口可访问。
+
+如果只是要修改spring security登出的url,可以通过如下方式进行修改,且不需要其他任何修改,其单单只是改变了logoutFilter匹配的url:
+```java
+http
+ .logout((logout) -> logout.logoutUrl("/my/logout/uri"))
+```
+
+但是,如果自定义了logout success endpoint(通过spring mvc建立的controller endpoint),那么需要为自定义的logout endpoint执行permit操作来允许用户访问。因为只有当spring security中的操作都完成后,才会指定自定义的endpoint操作。
+
+可以通过如下方式为自定义的登出endpoint进行授权:
+```java
+http
+ .authorizeHttpRequests((authorize) -> authorize
+ .requestMatchers("/my/success/endpoint").permitAll()
+ // ...
+ )
+ .logout((logout) -> logout.logoutSuccessUrl("/my/success/endpoint"))
+```
+> logoutSuccessUrl为logout操作执行成功后,重定向到的url,该值默认为`/login?logout`。
+>
+> logoutUrl则是触发logout操作的url。
+
+
+
+
+
+
+
+