当前位置 : 首页 » 文章分类 :  开发  »  Spring-Security

Spring-Security

Spring Security 笔记

Spring Security 的底层是通过一系列的 Filter 来管理的,每个 Filter 都有其自身的功能,它们的顺序也非常重要。


SpringCloud Gateway 中使用 Spring Security

由于 SpringCloud Gateway 基于 WebFlux 并且不兼容 SpringMVC,因此对于 Security 的配置方式也跟普通 SpringBoot 项目中的配置方式不同。

配置 Spring Security,对所有 /actuator/** 进行 httpBasic 认证

@EnableWebFluxSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfiguration {
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
        httpSecurity.authorizeExchange()
                    .pathMatchers("/actuator/**").authenticated()
                    .anyExchange().permitAll()
                    .and().httpBasic()
                    .and().formLogin()
                    .and().csrf().disable();
        return httpSecurity.build();
    }
}

Springcloud Gateway 整合 Spring Security 配置与踩坑
https://blog.csdn.net/UserFrank/article/details/118281035

集成Spring Cloud Security和Spring Cloud Gateway
https://cloud.tencent.com/developer/article/2264289


httpBasic 认证的 API 调用传参方式

httpSecurity.httpBasic().and().formLogin();

在 Spring Security 中,通过 HTTP Basic Authentication 的方式进行认证,调用方在发送请求时需要在 header 中设置 Authorization 字段,其值为 “Basic “+ base64编码的用户名和密码(username:password),即 Basic base64(username:password)

具体如下:
1、将用户名和密码以 username:password 的形式进行拼接。
2、使用 Base64 对拼接后的字符串进行编码,得 dXNlcjpwYXNzd29yZA==
3、将编码后的字符串添加到 Authorization 字段中,并在其前面添加 Basic
例如
curl http://localhost:8181/v2/api-docs -H ‘Authorization: Basic dXNlcjpwYXNzd29yZA==’


默认配置

添加依赖后,不作任何配置,默认全部接口都需要认证才能访问,否则报错

{
    "timestamp": "2023-02-03 15:07:54",
    "status": 403,
    "error": "Forbidden",
    "path": "/path-to-api"
}
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

HttpSecurity 配置

anyRequest 匹配所有请求路径
access SpringEl 表达式结果为 true 时可以访问
anonymous 匿名可以访问
denyAll 用户不能访问
fullyAuthenticated 用户完全认证可以访问(非remember-me下自动登录)
hasAnyAuthority 如果有参数,参数表示权限,则其中任何一个权限可以访问
hasAnyRole 如果有参数,参数表示角色,则其中任何一个角色可以访问
hasAuthority 如果有参数,参数表示权限,则其权限可以访问
hasIpAddress 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
hasRole 如果有参数,参数表示角色,则其角色可以访问
permitAll 用户可以任意访问
rememberMe 允许通过remember-me登录的用户访问
authenticated 用户登录后可访问


CSRF 不支持 POST 导致 permitAll() 不起作用

httpSecurity.permitAll 并不会绕开 springsecurity 的过滤器验证,配置的 url 还是会通过 spring security 过滤器。
webSecurity.ignoring 是完全绕过了spring security 的所有 filter,相当于不走 spring security

@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
    private static final String[] NEED_AUTH_URLS = {
            "/hello1",
            "/hello2/**"
    };

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .antMatchers(NEED_AUTH_URLS).authenticated()
                .anyRequest().permitAll()
                .and().formLogin()
                .and().httpBasic();
    }
}

上面的配置并不能实现只认证某些接口,放行其他接口,全部接口都会经过 filter,导致 403 未授权,意味着已经登录认证成功(否则报401),但没有访问对应api的权限

打开debug日志,看到
Invalid CSRF token found for http://localhost:8080/path-to-api
org.springframework.security.web.csrf.CsrfFilter 中

原因:RESTful 技术与 CSRF(Cross-site request forgery 跨站请求伪造)的冲突造成的,CSRF 默认支持的方法: GET|HEAD|TRACE|OPTIONS,不支持POST。可以在security在配置中禁用

解决:
禁用 csrf

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.authorizeRequests()
            .antMatchers(NEED_AUTH_URLS).authenticated()  // 需要认证
            .anyRequest().permitAll()  // 其他不需要认证
            .and().formLogin() // 开启表单登录
            .and().httpBasic() // 基础账号密码认证
            .and().csrf().disable(); // 关闭csrf
}

上一篇 Tesseract

下一篇 Mockito

阅读
评论
912
阅读预计3分钟
创建日期 2023-02-03
修改日期 2024-03-03
类别
标签

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论