跳至主要內容

踏入山门

荒流2023年2月16日大约 4 分钟约 1075 字

1. 概念

Spring Security 是 Spring 家族中的一个安全管理框架,相比于另外一个安全框架 Shiro,Spring Security 提供了更丰富的功能,社区资源也更丰富。

一般来说,中大型的项目使用 Spring Security 来做安全框架,小项目用 Shiro 的比较多,因为相比于 SpringSecurity,Shiro 的上手更加简单。

一般 Web 应用需要进行认证和授权:

认证和授权也是 SpringSecurity 作为安全框架的核心功能。

2. 使用上手

2.1 普通的 Spring Boot Web 项目

maven 依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chuan</groupId>
    <artifactId>play-spring-security</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>play-spring-security</name>
    <description>play-spring-security</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

启动类:

@SpringBootApplication
public class PlaySpringSecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(PlaySpringSecurityApplication.class, args);
    }
}

写一个 controller:

@RequestMapping("/play/spring/security")
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, spring security!";
    }
}

此时,浏览器访问相应的 http://localhost:8080/play/spring/security/hello 接口,毫无疑问能够正常访问:

image-20230215225133172

2.2 整合 Spring Security

在 Spring Boot 项目中整合 Spring Security,只需要在 maven 依赖中引入相应的 starter 即可,无需其他配置:

    <dependencies>
        <!-- ... -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.7.8</version>
        </dependency>
        <!-- ... -->
    </dependencies>

一旦整合进来 Spring Security,你会发现当再次访问 http://localhost:8080/play/spring/security/hello 时,会自动跳转到一个 login 界面,如下图:

image-20230215225342244

这说明,Spring Security 对你的接口进行了访问限制,必须通过登录进行认证成功后,才能正常访问原来的接口。

我们输出用户名和密码后,发现原来的接口终于恢复正常访问了。其中的用户名密码从哪里取呢?由于我们引入 Spring Security 后没有进行过任何其他配置,因此默认的用户名是user,而默认的密码则需要从项目启动时的控制台输出中获取到,如下:

image-20230215230137238

由此,我们便相当于引入了 Spring Security 带来的认证功能。它赋予了我们一个登录界面(html),并提供相应的登录接口(相当于自带了几个 controller):

针对上述自带的登录界面,在实际项目中我们当然会根据实际需求去自定义各种样式的界面,而不会直接用 Spring Security 自带的这个,因此在实际项目中我们其实只要用到 Spring Security 提供的这些后台接口就可以了,前端页面会进行重写。

3. Spring Security 原理初探

Spring Security 的原理其实就是一个过滤器链,其中包含了各种功能的过滤器。我们用下图来大概了解一下其中涉及的部分核心过滤器:

image-20230215231945666
image-20230215231945666

实际上,我们可以通过 debug 来查看系统中 Spring Security 过滤器链中有哪些过滤器以及它们的顺序,通过获取 DefaultSecurityFilterChain 这个 bean 即可:

image-20230215233326393
image-20230215233326393

上述一系列过滤器都属于 Spring Security 中的默认实现,在实际项目中,我们需要自定义一些方案,此时只要针对过滤器链中的特定过滤器,提供一个自己的实现类以替换默认实现即可。