阅读spring security文档
This commit is contained in:
111
spring/Spring Security/spring_security_sgg.md
Normal file
111
spring/Spring Security/spring_security_sgg.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Spring Security
|
||||
Spring Security提供了authentication(认证)、authorization(授权)、protection against common attacks(防御常见攻击)的功能。
|
||||
|
||||
Spring Security提供了针对如下常见攻击的防御:
|
||||
- CSRF
|
||||
- Http Headers
|
||||
- Http Requests
|
||||
|
||||
## 默认自动装配
|
||||
当web项目引入Spring Security依赖后,如果不做任何特殊处理,Spring Security会默认为项目配置一个登录校验。当用户没有进行登录而访问页面时,会拦截用户请求返回一个登录页,在用户登录成功之后,再会将url重定向到用户先前请求的页面。
|
||||
|
||||
### Spring Security默认为项目做的操作
|
||||
1. 保护web项目的url,Spring Security要求与http接口进行的任何交互都需要进行身份认证
|
||||
2. Spring Security会在web项目启动时生成一个默认的用户,用户名为user,用户密码会通过日志打出
|
||||
3. Spring Security会为项目生成默认的登录和注销页面,并提供了基本登录流程和注销流程
|
||||
4. 对于http请求,如果在没有进行身份认证的情况下,会重定向到登录页面
|
||||
|
||||
## Spring Security底层结构
|
||||
Spring Security底层通过Filter链来实现。
|
||||
|
||||
### DelegatingFilterProxy
|
||||
spring boot提供了Filter的实现类DelegatingFilterProxy,该类将实际的过滤逻辑委托给另一个filter bean对象。
|
||||
|
||||
通过DelegatingFilterProxy,可以将servlet container和spring容器结合起来,将DelegatingFilterProxy对象作为filter注册到servlet container中,然后DelegatingFilterProxy把实际过滤逻辑委托给spring context中的bean对象,如此可以通过向spring容器中注册bean对象来自定义filter chain逻辑。
|
||||
|
||||
### SecurityFilterChain
|
||||
DelegationFilterProxy将filter逻辑委托给了FilterChainProxy。
|
||||
|
||||
而FilterProxyChain则是包含了SecurityFilterChain(并且可以包含多个SecurityFilterChain)。SecurityFilterChain中包含的才是多个filter bean对象。
|
||||
|
||||
如果FilterChainProxy中注册了多个SecurityFilterChain,那么将由FilterChainProxy来决定实际调用哪个SecurityFilterChain。只有匹配的第一个SecurityFilterChain会被实际调用。
|
||||
|
||||
> 如果当spring容器中存在多个SecurityFilterChian bean对象,那么可以通过@Order注解来指定SecurityFilterChain bean对象的顺序,从而调整不同SecurityFilterChain的优先级
|
||||
|
||||
示例如下:
|
||||
```java
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(Customizer.withDefaults())
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.httpBasic(Customizer.withDefaults())
|
||||
.formLogin(Customizer.withDefaults());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
上述代码注册的SecurityFilterChain将拥有如下顺序:
|
||||
| Filter | Added by |
|
||||
| :-: | :-: |
|
||||
| CsrfFilter | HttpSecurity#csrf |
|
||||
| UsernamePasswordAuthenticationFilter | HttpSecurity#formLogin |
|
||||
| BasicAuthenticationFilter | HttpSecurity#httpBasic |
|
||||
| AuthorizationFilter | HttpSecurity#authorizeHttpRequests |
|
||||
|
||||
> 通常,security filter chain都是先执行authentication再执行authorization
|
||||
|
||||
### 自定义Filter
|
||||
除了使用Spring Security预置的filter外,还可以使用自定义的filter,自定义filter使用示例如下:
|
||||
```java
|
||||
// Filter定义
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
|
||||
public class TenantFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
String tenantId = request.getHeader("X-Tenant-Id"); (1)
|
||||
boolean hasAccess = isUserAllowed(tenantId); (2)
|
||||
if (hasAccess) {
|
||||
filterChain.doFilter(request, response); (3)
|
||||
return;
|
||||
}
|
||||
throw new AccessDeniedException("Access denied"); (4)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
```java
|
||||
// 将自定义filter添加到SecurityFilterChain中
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
// ...
|
||||
.addFilterBefore(new TenantFilter(), AuthorizationFilter.class);
|
||||
return http.build();
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user