那些年背过的题:Spring Security概览

282 阅读2分钟

Spring Security 是一个强大且高度可定制的安全框架,用于在 Java 应用程序中提供认证和授权功能。它是现代 Java 开发中必不可少的一部分,能够帮助开发者轻松地实现复杂的安全需求。

主要功能

  1. 认证(Authentication) :验证用户身份。
  2. 授权(Authorization) :控制用户访问不同资源的权限。
  3. 防止常见攻击:如 CSRF(跨站请求伪造)、会话固定攻击等。
  4. 集成其他安全系统:与 LDAP、OAuth2、JWT 等进行集成。
  5. 安全上下文(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);
    }
}