Spring Security 是一个强大且高度可定制的安全框架,用于在 Java 应用程序中提供认证和授权功能。它是现代 Java 开发中必不可少的一部分,能够帮助开发者轻松地实现复杂的安全需求。
主要功能
- 认证(Authentication) :验证用户身份。
- 授权(Authorization) :控制用户访问不同资源的权限。
- 防止常见攻击:如 CSRF(跨站请求伪造)、会话固定攻击等。
- 集成其他安全系统:与 LDAP、OAuth2、JWT 等进行集成。
- 安全上下文(Security Context) :持有当前认证信息的上下文环境。
基本概念
AuthenticationManager:处理认证请求的核心接口。GrantedAuthority:表示单个权限的抽象接口。UserDetailsService:从某个数据源加载用户信息的接口。SecurityContext:持有当前认证信息的上下文环境。
示例项目配置
1. 添加依赖
首先,在你的 pom.xml 文件中添加 Spring Security 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2. 认证(Authentication)
认证是指验证用户身份,确保用户是合法的。Spring Security 提供多种方式进行认证,包括基于内存的认证、数据库认证、LDAP 认证等。
内存认证示例
通过扩展 WebSecurityConfigurerAdapter 类来配置内存中的用户。
WebSecurityConfig.java:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
}
3. 授权(Authorization)
授权是指确定用户能访问哪些资源。通过配置 HttpSecurity 对象,可以保护不同的 URL 路径。
在上面的代码中,我们定义了只有角色为 ADMIN 的用户可以访问 /admin/** 路径,而所有已认证用户可以访问其他路径。
4. 防止常见攻击
Spring Security 提供了一些默认的防护措施,比如 CSRF 防护。你可以通过配置 HttpSecurity 对象来启用或禁用这些功能。
CSRF (Cross-Site Request Forgery) 默认情况下是启用的。如果需要禁用,可以添加以下配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() // 禁用 CSRF 防护
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
5. 安全上下文(Security Context)
SecurityContext 持有当前认证的信息,并且可以在应用程序的任意地方进行访问。
例如,可以在控制器中获取当前用户的信息:
MainController.java:
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/home")
public String home(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentUserName = authentication.getName();
model.addAttribute("username", currentUserName);
return "home";
}
}
6. 创建视图
login.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username"/>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</div>
<div>
<button type="submit">Sign in</button>
</div>
</form>
</body>
</html>
home.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome Home!</h1>
<p>Logged in as: <span th:text="${#authentication.name}"></span></p>
<a th:href="@{/logout}">Logout</a>
</body>
</html>
admin.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Admin Page</title>
</head>
<body>
<h1>Welcome Admin!</h1>
<p>Logged in as: <span th:text="${#authentication.name}"></span></p>
<a th:href="@{/logout}">Logout</a>
</body>
</html>
4. 启动应用程序
确保所有配置已完成,通过运行 SpringBootApplication 主类来启动应用程序。
Application.java:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}