阅读spring security文档

This commit is contained in:
asahi
2024-03-18 21:09:23 +08:00
parent eff9847a5d
commit ace697e380

View File

@@ -38,6 +38,10 @@
- [将token持久化到数据库中](#将token持久化到数据库中) - [将token持久化到数据库中](#将token持久化到数据库中)
- [RememberMe的接口及其实现](#rememberme的接口及其实现) - [RememberMe的接口及其实现](#rememberme的接口及其实现)
- [TokenBasedRememberMeService](#tokenbasedremembermeservice) - [TokenBasedRememberMeService](#tokenbasedremembermeservice)
- [匿名身份认证](#匿名身份认证)
- [匿名认证配置](#匿名认证配置)
- [处理logout](#处理logout)
- [自定义登出url](#自定义登出url)
# Spring Security # Spring Security
@@ -732,5 +736,83 @@ RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
return 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
<bean id="anonymousAuthFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider"
class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/>
</bean>
```
`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 authenticationTokenRememberMeServices / PersistentTokenRememberMeServices
5. 清空任何csrf token (LogoutSuccessEventPublishingLogoutHandler)
6. 发送LogoutSuccessEventLogoutSuccessEventPublishingLogoutHandler
### 自定义登出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。