Spring Security是Spring组织提供的一个开源安全框架,基于Spring开发,所以非常适合在Spring Boot中使用。
官方文档地址:https://docs.spring.io/spring-security/reference/index.html
GitHub地址:https://github.com/spring-projects/spring-security
目前最新的版本是6.1.4,提供了许多新功能,需使用JDK 17及以上版本。
Spring Security作为一个功能完善的安全框架,具有以下特性:
. ├── springboot3-cloud-example │ ├── spring-security │ │ ├── hello-security │ │ │ ├── src │ │ │ └── pom.xml │ │ └── pom.xml | └── pom.xml
4.0.0 com.gm springboot3-cloud-example springboot3-cloud-example 0.0.1-SNAPSHOT pom SpringBoot3-Cloud进阶实战示例 3.1.4 2022.0.0 2022.0.0.0 UTF-8 17 17 spring-security org.projectlombok lombok provided org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring-cloud-alibaba.version} pom import ${project.name} src/main/resources true org.springframework.boot spring-boot-maven-plugin ${spring-boot.version} ${project.build.finalName} true repackage dev dev nacos nacos true test test nacos nacos
springboot3-cloud-example com.gm 0.0.1-SNAPSHOT 4.0.0 pom spring-security hello-security
4.0.0 spring-security com.gm 0.0.1-SNAPSHOT hello-security jar 入门示例 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.security spring-security-test test
spring-boot-starter-security是Spring Boot官方提供的启动器,提供了自动配置和依赖包管理功能,主要包含以下几个子模块:
- spring-security-core: 核心包,包含核心认证和访问权限功能类和接口、远程支持和基本配置
- spring-security-web: Web框架集成包,包含过滤器和相关的安全基础设施代码
- spring-security-config:包含security命名空间解析代码和Java配置代码
接下来我们随便编写一个web访问接口,方便后面进行测试。
package com.gm.security.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "hello spring security"; } }
package com.gm.security; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class HelloSecurityApplication { public static void main(String[] args) { SpringApplication.run(HelloSecurityApplication.class, args); } }
我们把项目启动起来后,在浏览器中对/hello进行访问,会发现/hello是无法直接访问的。在访问/hello之前会自动跳转到/login地址,进入到一个登录界面。这是因为Spring Boot中"约定大约配置"的规则,只要我们添加了Spring Security的依赖包,就会自动开启安全限制,在访问Web接口之前会进行安全拦截。只有输入了用户名和密码,才能访问项目中的Web接口,上述过程如下图所示:
此时登录界面中,要求我们输入用户名和密码。这个默认的用户名是user,密码是一个用UUID生成的随机字符串。在每次启动项目时,都可以在控制台中看到生成的随机密码,如下图所示:
能有小伙伴会很好奇,这个随机的密码到底是在哪里生成的呢?
让我们分析一下Spring Security的源码,来看看这个密码的生成策略。这个默认的用户名和密码其实是在SecurityProperties类中定义的,源码如下图:
而控制台上打印的密码日志,是在UserDetailsServiceAutoConfiguration类的getOrDeducePassword方法中输出的。
我们只要把这个随机密码,复制粘贴到登录页面的密码框中,就可以访问/hello接口了。
从上面的源码分析可知,默认的登录密码是利用UUID生成的随机字符串,很明显如果我们使用这个字符串作为登录密码,就太麻烦了。那么有没有更方便的登录账户呢?
Spring Security框架允许我们自己配置用户名和密码,并且提供了2种方式来进行自定义用户名和密码:
在application.yml配置文件新增以下内容:
spring: security: user: name: admin password: 123456
新建配置类SecurityConfig,新增以下内容:
package com.gm.security.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @Configuration @EnableWebSecurity(debug = true) public class SecurityConfig { @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("admin").password("123456").roles("USER").build(); return new InMemoryUserDetailsManager(new UserDetails[]{user}); } }
实现以上2种方式的任何一种,我们重启项目,这时候利用我们自己配置的用户名和密码,就可以访问/hello接口了。
在后续章节中会对以上2种实现方式进行具体源码分析。
至此我们入门案例搭建完毕。我们只需要添加一个Spring Security依赖包,就可以实现Web安全控制。