spring-security

初始SpringSecurity安全框架

在介绍之前,我们先来体验一下SpringSecurity。
我们在一个新建springboot2的项目中,来引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  • 首先,用户通过Controller向未授权的资源发出未经身份验证的GetMapper请求/private。
  • 然后在浏览器URL中输入项目的启动端口+private,你就会发现自己跳转到了login登录页面,打开idea发现控制台多了一串字符串,通过用户名=user + 密码=字符串可以登录成功,并访问到private,这就是接下来要讲的。

认证(你是谁?)

表单登录

本节检查基于表单的登录在 Spring 安全性中的工作原理。 首先,我们看到用户如何被重定向到登录表单:

  • 一、Spring Security的AuthorizationFilter设置了anyRequest().authenticated(); //默认拦截所有的请求。
  • 二、AuthorizationFilter如果访问被拦截则会通过ExceptionTranslationFilter(处理安全异常的安全过滤器)处理.AccessDeniedException异常。
  • 三、由于用户未经过身份验证,因此ExceptionTranslationFilter会启动身份验证,并使用配置的 AuthenticationEntryPoint 将重定向到登录页面。
  • 四、重定向到login页面
    用户提交用户名和密码后,将对用户名和密码进行身份验证。
    身份验证处理过滤器

在此拦截器中验证用户名和密码是否正确,并指向到不同的拦截器链进行处理。

授权(你能做什么)

我们可以使用authorizeHttpRequests来定制不同的放行策略。

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize
			.requestMatchers("/resources/**", "/signup", "/about").permitAll()
			.requestMatchers("/admin/**").hasRole("ADMIN")
			.requestMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))
			// .requestMatchers("/db/**").access(AuthorizationManagers.allOf(AuthorityAuthorizationManager.hasRole("ADMIN"), AuthorityAuthorizationManager.hasRole("DBA")))
			.anyRequest().denyAll()
		);

	return http.build();
}
  • 指定了多个授权规则。 每个规则都按照声明的顺序进行考虑。
  • 我们指定了任何用户都可以访问的多个 URL 模式。 具体而言,如果 URL 以“/resources/”开头、等于“/signup”或等于“/about”,则任何用户都可以访问请求。
  • 任何以“/admin/”开头的 URL 都将仅限于具有“ROLE_ADMIN”角色的用户。 您会注意到,由于我们正在调用该方法,因此我们不需要指定“ROLE_”前缀。hasRole
  • 任何以“/db/”开头的 URL 都要求用户同时具有“ROLE_ADMIN”和“ROLE_DBA”。 您会注意到,由于我们使用的是表达式,因此不需要指定“ROLE_”前缀。hasRole
  • 4中的相同规则,可以通过组合多个.AuthorizationManager
  • 任何尚未匹配的 URL 都将被拒绝访问。 如果您不想意外忘记更新授权规则,这是一个很好的策略。

请求匹配

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher("/api/**")
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers("/user/**").hasRole("USER")
				.requestMatchers("/admin/**").hasRole("ADMIN")
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}
  • 配置为仅应用于以HttpSecurity/api/
  • 允许具有该角色的用户访问以 开头的网址/user/USER
  • 允许具有该角色的用户访问以 开头的网址/admin/ADMIN
  • 任何其他不符合上述规则的请求都需要身份验证

防范漏洞利用

针对跨站点请求伪造攻击(CSRF)攻击

在SpringSecurity中,默认是启用了防范CSRF策略,但可以设置禁用CSRF

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.csrf(csrf -> csrf.disable());
		return http.build();
	}
}

在 Spring Security 中,专门提供了一个 CsrfFilter 来实现对 CSRF 的保护。CsrfFilter 拦截请求,并允许使用 GET、HEAD、TRACE 和 OPTIONS 等 HTTP 方法的请求。而针对 PUT、POST、DELETE 等可能会修改数据的其他请求,CsrfFilter 则希望接收包含 csrf_token 的消息头。如果这个消息头不存在或包含不正确的 csrf_token 值,应用程序将拒绝该请求并将响应的状态设置为 403。
CSRF攻击的原理是这样的:

CSRF的攻击者只是利用了通过认证的Cookie。
CsrfFilter就在返回给客户端的表单里隐藏域的Value里和请求头中放置随机值,并在服务端也放置这个随机值,在用户发送请求时来校验这个随机值是否正确,如果不正确则拒绝访问。

但是在微服务中不能使用这种方式,因为客户端访问了一次实例,下发了Token。但微服务的多模块及负载均衡的特性,我们下一次携带Token发送的请求,未必是上一次的实例。
02033)]

但是在微服务中不能使用这种方式,因为客户端访问了一次实例,下发了Token。但微服务的多模块及负载均衡的特性,我们下一次携带Token发送的请求,未必是上一次的实例。
后端可以把随机字符串存入到Redis里,响应给前端,前端携带字符串访问Redis来验证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CaryJohnson

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值