1. Spring Security简介
Spring Security的历史和目标
Spring Security是一个功能强大且可高度定制的身份验证和访问控制框架。该框架的历史可以追溯到2003年,当时它作为一个名为Acegi Security的开源项目开始,并在2008年正式被纳入Spring框架家族并改名为Spring Security。它就此成为Spring旗下的一个重要项目。
Spring Security的主要目标是为Java应用程序提供全面的安全性解决方案。这包括认证(确定谁在尝试访问),授权(确定他们可以访问哪些资源)和攻击防护(防止攻击者包括CSRF攻击等),同时也能够更好地防止会话劫持等许多网络安全威胁。
Spring Security主要功能
身份验证:Spring Security提供了一套完善的身份验证机制。开发者可以选择基于表单的验证,HTTP基本验证,HTTP摘要验证,OpenID验证等。
授权:一旦身份验证过程完成,Spring Security还会提供另一层安全控制,决定用户是否有权访问某个特定的资源或执行某个特定的操作。
**防止跨站请求伪造(CSRF)**:Spring Security提供了防止CSRF的特性,可以保护应用程序免受CSRF攻击。
会话管理:该框架提供了会话管理,包括支持会话创建策略以及会话定期失效等功能。
密码加密:Spring Security提供了密码编码器,保证密码在持久化到数据库之前已经被安全地加密。
2. Spring Security核心概念
认证与授权
认证是指确定某人是谁的过程。在大多数情况下,这涉及将用户名和密码与存储的凭据(如数据库中的用户名和密码)进行比较。
授权是指确定已认证用户可以对系统中的哪些资源执行哪些操作的过程。例如,授权可以决定用户是否可以访问某个特定的web页面,或者用户是否可以读取或修改数据库中的特定行。
Users, Roles 和 Privileges
在Spring Security中,用户身份通常通过用户名表示,权限通常表示用户可以做什么。角色则是一种实现权限模型的方式,它是权限的集合。一个用户可分配多个角色,并且每个角色具有一系列权限。例如,我们可能有一个管理员角色,该角色包含对所有资源的全权访问权限。
SecurityContext 和 SecurityContextHolder
SecurityContext 是 Spring Security 用于持有安全相关信息的接口,其中包含了当前使用系统的用户信息。SecurityContextHolder 是一个持有 SecurityContext 的容器,存储策略默认是使用ThreadLocal 保存 SecurityContext。
每次进行请求调用时,Spring Security 会创建一个 SecurityContext,并将其放置在 SecurityContextHolder 中,用于在后续的处理过程中使用,这都是在 Spring Security 的过滤器链中完成的。
当请求处理完成后,Spring Security 将 SecurityContext 从 SecurityContextHolder 中清理掉,以确保下次请求不会重复使用。
这两个组件是 Spring Security 中的核心组件,用于存储和管理当前用户的安全相关信息。
3. Spring Security配置
使用Spring Boot设置Spring Security的简单配置
在Spring Boot中,你可以通过增加
spring-boot-starter-security
依赖来轻松的开启Spring Security的默认配置,这个依赖可以在pom.xml文件中添加:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
一旦你添加了该依赖,Spring Boot就会自动配置Spring Security的一些默认设置,例如基于表单的登录,以及默认生成的用户名和密码。
自定义Spring Security配置
尽管Spring Boot的默认配置可以快速起步,但在复杂的业务场景中,通常需要进行自定义的安全配置。 自定义Spring Security配置的核心是创建一个扩展
WebSecurityConfigurerAdapter
的类。例如:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password(passwordEncoder().encode("password")).roles("USER") .and() .withUser("admin").password(passwordEncoder().encode("admin")).roles("A