Spring Boot 安全认证与授权

Spring Boot 安全认证与授权

Spring Boot 安全认证与授权

在这里插入图片描述
22.1 学习目标与重点提示

学习目标:掌握Spring Boot安全认证与授权的核心概念与使用方法,包括Spring Security的定义与特点、Spring Boot与Spring Security的集成、Spring Boot与Spring Security的配置、Spring Boot与Spring Security的认证、Spring Boot与Spring Security的授权、Spring Boot与Spring Security的实际应用场景,学会在实际开发中处理安全认证与授权问题。
重点:Spring Security的定义与特点Spring Boot与Spring Security的集成Spring Boot与Spring Security的配置Spring Boot与Spring Security的认证Spring Boot与Spring Security的授权Spring Boot与Spring Security的实际应用场景

22.2 Spring Security概述

Spring Security是Java开发中的重要组件。

22.2.1 Spring Security的定义

定义:Spring Security是Spring Boot提供的安全框架。
作用

  • 实现用户认证。
  • 实现用户授权。
  • 提供安全的编程模型。

常见的安全框架

  • Spring Security:Spring Boot提供的安全框架。
  • Shiro:Apache Shiro是一款开源的安全框架。

✅ 结论:Spring Security是Spring Boot提供的安全框架,作用是实现用户认证、用户授权、提供安全的编程模型。

22.2.2 Spring Security的特点

定义:Spring Security的特点是指Spring Security的特性。
特点

  • 全面性:Spring Security提供了全面的安全功能。
  • 可扩展性:Spring Security可以扩展到多个应用程序之间的安全通信。
  • 易用性:Spring Security提供了易用的编程模型。
  • 整合性:Spring Security可以与Spring Boot、Spring Cloud等整合。

✅ 结论:Spring Security的特点包括全面性、可扩展性、易用性、整合性。

22.3 Spring Boot与Spring Security的集成

Spring Boot与Spring Security的集成是Java开发中的重要内容。

22.3.1 集成Spring Security的步骤

定义:集成Spring Security的步骤是指使用Spring Boot与Spring Security集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置Spring Security。
  4. 创建用户服务类。
  5. 创建控制器类。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 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-test</artifactId><scope>test</scope></dependency></dependencies>

Spring Security配置类:

importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("admin123").roles("ADMIN").and().withUser("user").password("user123").roles("USER");}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}

控制器类:

importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.GetMapping;@ControllerpublicclassSecurityController{@GetMapping("/")publicStringindex(){return"index";}@GetMapping("/login")publicStringlogin(){return"login";}@GetMapping("/user")publicStringuser(){return"user";}@GetMapping("/admin")publicStringadmin(){return"admin";}}

视图模板文件(src/main/resources/templates/index.html):

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>首页</title><style>body{font-family: Arial, sans-serif;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f5f5f5;}.container{background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}h1{color: #333;margin-bottom: 20px;}a{text-decoration: none;color: #007bff;margin-right: 20px;}a:hover{text-decoration: underline;}</style></head><body><divclass="container"><h1>首页</h1><ahref="/login">登录</a><ahref="/user">用户页面</a><ahref="/admin">管理员页面</a></div></body></html>

视图模板文件(src/main/resources/templates/login.html):

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>登录</title><style>body{font-family: Arial, sans-serif;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f5f5f5;}.container{background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}h1{color: #333;margin-bottom: 20px;}form{display: flex;flex-direction: column;}label{margin-bottom: 5px;color: #333;}input{margin-bottom: 10px;padding: 8px;border: 1px solid #ddd;border-radius: 5px;}button{padding: 10px;background-color: #007bff;color: white;border: none;border-radius: 5px;cursor: pointer;}button:hover{background-color: #0056b3;}a{text-decoration: none;color: #007bff;margin-top: 10px;text-align: center;}a:hover{text-decoration: underline;}</style></head><body><divclass="container"><h1>登录</h1><formth:action="@{/login}"method="post"><labelfor="username">用户名:</label><inputtype="text"id="username"name="username"required><labelfor="password">密码:</label><inputtype="password"id="password"name="password"required><buttontype="submit">登录</button></form><ahref="/">返回首页</a></div></body></html>

视图模板文件(src/main/resources/templates/user.html):

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>用户页面</title><style>body{font-family: Arial, sans-serif;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f5f5f5;}.container{background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}h1{color: #333;margin-bottom: 20px;}a{text-decoration: none;color: #007bff;margin-right: 20px;}a:hover{text-decoration: underline;}</style></head><body><divclass="container"><h1>用户页面</h1><ahref="/">返回首页</a><ahref="/logout">登出</a></div></body></html>

视图模板文件(src/main/resources/templates/admin.html):

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>管理员页面</title><style>body{font-family: Arial, sans-serif;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f5f5f5;}.container{background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}h1{color: #333;margin-bottom: 20px;}a{text-decoration: none;color: #007bff;margin-right: 20px;}a:hover{text-decoration: underline;}</style></head><body><divclass="container"><h1>管理员页面</h1><ahref="/">返回首页</a><ahref="/logout">登出</a></div></body></html>

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpMethod;importorg.springframework.http.ResponseEntity;importjava.util.Base64;importjava.util.Map;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classSpringSecurityApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestIndexPage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/",String.class);assertThat(response).contains("首页");}@TestvoidtestUserPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/user",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestUserPageWithUserAuthentication(){String credentials ="user:user123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/user",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("用户页面");}@TestvoidtestAdminPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/admin",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestAdminPageWithAdminAuthentication(){String credentials ="admin:admin123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/admin",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("管理员页面");}}

✅ 结论:集成Spring Security的步骤包括创建Spring Boot项目、添加所需的依赖、配置Spring Security、创建用户服务类、创建控制器类、测试应用。

22.4 Spring Boot与Spring Security的认证

Spring Boot与Spring Security的认证是Java开发中的重要内容。

22.4.1 基于内存的认证

定义:基于内存的认证是指Spring Security提供的一种认证方式。
作用

  • 实现用户认证。
  • 提供安全的编程模型。

示例

importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("admin123").roles("ADMIN").and().withUser("user").password("user123").roles("USER");}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}

✅ 结论:基于内存的认证是指Spring Security提供的一种认证方式,作用是实现用户认证、提供安全的编程模型。

22.4.2 基于数据库的认证

定义:基于数据库的认证是指Spring Security提供的一种认证方式。
作用

  • 实现用户认证。
  • 提供安全的编程模型。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Security依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Data JPA依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2数据库依赖 --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

实体类:

importjavax.persistence.*;@Entity@Table(name ="user")publicclassUser{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateString username;privateString password;privateString role;publicUser(){}publicUser(String username,String password,String role){this.username = username;this.password = password;this.role = role;}// Getter和Setter方法publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}publicStringgetUsername(){return username;}publicvoidsetUsername(String username){this.username = username;}publicStringgetPassword(){return password;}publicvoidsetPassword(String password){this.password = password;}publicStringgetRole(){return role;}publicvoidsetRole(String role){this.role = role;}@OverridepublicStringtoString(){return"User{"+"id="+ id +",+ username +'\''+",+ password +'\''+",+ role +'\''+'}';}}

Repository接口:

importorg.springframework.data.jpa.repository.JpaRepository;importorg.springframework.stereotype.Repository;@RepositorypublicinterfaceUserRepositoryextendsJpaRepository<User,Long>{UserfindByUsername(String username);}

用户服务类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.security.core.GrantedAuthority;importorg.springframework.security.core.authority.SimpleGrantedAuthority;importorg.springframework.security.core.userdetails.UserDetails;importorg.springframework.security.core.userdetails.UserDetailsService;importorg.springframework.security.core.userdetails.UsernameNotFoundException;importorg.springframework.stereotype.Service;importjava.util.ArrayList;importjava.util.List;@ServicepublicclassUserDetailsServiceImplimplementsUserDetailsService{@AutowiredprivateUserRepository userRepository;@OverridepublicUserDetailsloadUserByUsername(String username)throwsUsernameNotFoundException{User user = userRepository.findByUsername(username);if(user ==null){thrownewUsernameNotFoundException("用户不存在:"+ username);}List<GrantedAuthority> authorities =newArrayList<>(); authorities.add(newSimpleGrantedAuthority("ROLE_"+ user.getRole()));returnorg.springframework.security.core.userdetails.User.builder().username(user.getUsername()).password(user.getPassword()).authorities(authorities).build();}}

Spring Security配置类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.authentication.AuthenticationManager;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;importorg.springframework.security.crypto.password.PasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredprivateUserDetailsServiceImpl userDetailsService;@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.userDetailsService(userDetailsService);}@BeanpublicPasswordEncoderpasswordEncoder(){returnNoOpPasswordEncoder.getInstance();}@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PostMapping;@ControllerpublicclassSecurityController{@AutowiredprivateUserRepository userRepository;@GetMapping("/")publicStringindex(){return"index";}@GetMapping("/login")publicStringlogin(){return"login";}@GetMapping("/user")publicStringuser(){return"user";}@GetMapping("/admin")publicStringadmin(){return"admin";}@PostMapping("/register")publicStringregisterUser(String username,String password,String role){User user =newUser(username, password, role); userRepository.save(user);return"redirect:/login";}}

视图模板文件(src/main/resources/templates/register.html):

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>注册</title><style>body{font-family: Arial, sans-serif;margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f5f5f5;}.container{background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}h1{color: #333;margin-bottom: 20px;}form{display: flex;flex-direction: column;}label{margin-bottom: 5px;color: #333;}input{margin-bottom: 10px;padding: 8px;border: 1px solid #ddd;border-radius: 5px;}select{margin-bottom: 10px;padding: 8px;border: 1px solid #ddd;border-radius: 5px;}button{padding: 10px;background-color: #007bff;color: white;border: none;border-radius: 5px;cursor: pointer;}button:hover{background-color: #0056b3;}a{text-decoration: none;color: #007bff;margin-top: 10px;text-align: center;}a:hover{text-decoration: underline;}</style></head><body><divclass="container"><h1>注册</h1><formth:action="@{/register}"method="post"><labelfor="username">用户名:</label><inputtype="text"id="username"name="username"required><labelfor="password">密码:</label><inputtype="password"id="password"name="password"required><labelfor="role">角色:</label><selectid="role"name="role"required><optionvalue="USER">用户</option><optionvalue="ADMIN">管理员</option></select><buttontype="submit">注册</button></form><ahref="/">返回首页</a></div></body></html>

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importorg.springframework.http.HttpEntity;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpMethod;importorg.springframework.http.ResponseEntity;importjava.util.Base64;importjava.util.Map;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classSpringSecurityApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestIndexPage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/",String.class);assertThat(response).contains("首页");}@TestvoidtestUserPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/user",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestUserPageWithUserAuthentication(){String credentials ="user:user123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/user",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("用户页面");}@TestvoidtestAdminPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/admin",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestAdminPageWithAdminAuthentication(){String credentials ="admin:admin123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/admin",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("管理员页面");}}

✅ 结论:基于数据库的认证是指Spring Security提供的一种认证方式,作用是实现用户认证、提供安全的编程模型。

22.5 Spring Boot与Spring Security的授权

Spring Boot与Spring Security的授权是Java开发中的重要内容。

22.5.1 基于角色的授权

定义:基于角色的授权是指Spring Security提供的一种授权方式。
作用

  • 实现用户授权。
  • 提供安全的编程模型。

示例

importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("admin123").roles("ADMIN").and().withUser("user").password("user123").roles("USER");}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}

✅ 结论:基于角色的授权是指Spring Security提供的一种授权方式,作用是实现用户授权、提供安全的编程模型。

22.5.2 基于权限的授权

定义:基于权限的授权是指Spring Security提供的一种授权方式。
作用

  • 实现用户授权。
  • 提供安全的编程模型。

示例

importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("admin123").roles("ADMIN").and().withUser("user").password("user123").roles("USER");}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}

✅ 结论:基于权限的授权是指Spring Security提供的一种授权方式,作用是实现用户授权、提供安全的编程模型。

22.6 Spring Boot与Spring Security的实际应用场景

在实际开发中,Spring Boot与Spring Security的应用场景非常广泛,如:

  • 实现用户的登录与登出。
  • 实现用户的角色管理。
  • 实现用户的权限管理。
  • 实现系统的安全审计。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.crypto.password.NoOpPasswordEncoder;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.GetMapping;@SpringBootApplicationpublicclassSecurityApplication{publicstaticvoidmain(String[] args){SpringApplication.run(SecurityApplication.class, args);}}@EnableWebSecurityclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth)throwsException{ auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("admin123").roles("ADMIN").and().withUser("user").password("user123").roles("USER");}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{ http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").antMatchers("/").permitAll().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}@ControllerclassSecurityController{@GetMapping("/")publicStringindex(){return"index";}@GetMapping("/login")publicStringlogin(){return"login";}@GetMapping("/user")publicStringuser(){return"user";}@GetMapping("/admin")publicStringadmin(){return"admin";}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classSecurityApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestIndexPage(){String response = restTemplate.getForObject("http://localhost:"+ port +"/",String.class);assertThat(response).contains("首页");}@TestvoidtestUserPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/user",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestUserPageWithUserAuthentication(){String credentials ="user:user123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/user",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("用户页面");}@TestvoidtestAdminPageWithoutAuthentication(){ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:"+ port +"/admin",Map.class);assertThat(response.getStatusCodeValue()).isEqualTo(302);}@TestvoidtestAdminPageWithAdminAuthentication(){String credentials ="admin:admin123";String base64Credentials =Base64.getEncoder().encodeToString(credentials.getBytes());HttpHeaders headers =newHttpHeaders(); headers.add("Authorization","Basic "+ base64Credentials);HttpEntity<String> entity =newHttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange("http://localhost:"+ port +"/admin",HttpMethod.GET, entity,String.class);assertThat(response.getStatusCodeValue()).isEqualTo(200);assertThat(response.getBody()).contains("管理员页面");}}

输出结果

  • 访问http://localhost:8080/:返回首页。
  • 访问http://localhost:8080/login:返回登录页面。
  • 访问http://localhost:8080/user:返回用户页面。
  • 访问http://localhost:8080/admin:返回管理员页面。

✅ 结论:在实际开发中,Spring Boot与Spring Security的应用场景非常广泛,需要根据实际问题选择合适的安全框架。

总结

本章我们学习了Spring Boot安全认证与授权,包括Spring Security的定义与特点、Spring Boot与Spring Security的集成、Spring Boot与Spring Security的配置、Spring Boot与Spring Security的认证、Spring Boot与Spring Security的授权、Spring Boot与Spring Security的实际应用场景,学会了在实际开发中处理安全认证与授权问题。其中,Spring Security的定义与特点、Spring Boot与Spring Security的集成、Spring Boot与Spring Security的配置、Spring Boot与Spring Security的认证、Spring Boot与Spring Security的授权、Spring Boot与Spring Security的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

OpenClaw部署与配置教程:在Mac mini上接入国产大模型与飞书

一、准备工作 项目说明一台Mac mini云服务器、旧电脑、树莓派也可以飞书账号用来创建机器人国产模型的apiopenclaw的在配置时仅显示国际的大模型,国产模型需要单独配置 二、部署OpenClaw到mac mini 2.1 快速部署 1. 稳定版安装:在终端输入以下命令 curl -fsSL https://openclaw.ai/install.sh |bash 2. 测试版安装(可能包含Bug) curl -fsSL https://openclaw.ai/install.sh |bash -s -- --beta 2.2 同意免责声明 安装好后,将会出现一个问题:是否知晓风险,选择Yes就行。 2.3 配置模式选择 选择“QuickStart”

By Ne0inhk
Linux操作系统从入门到实战(二)手把手教你安装VMware17pro与CentOS 9 stream,实现Vim配置,并配置C++环境

Linux操作系统从入门到实战(二)手把手教你安装VMware17pro与CentOS 9 stream,实现Vim配置,并配置C++环境

Linux操作系统从入门到实战(二)手把手教你安装VMware17pro与CentOS 9.0 stream,实现Vim配置,并编译C++文件 * 前言 * 一、安装VMware17pro * 二、安装CentOS9.0 * 2.1 为什么选择CentOS9,与CentOS7对比 * 2.1 官网下载CentOS9.0 * 2.2 国内清华大学镜像下载CentOS9.0 * 三、实现Linux环境搭建 * 四、配置Vim环境 * 1. 安装必要的软件 * 2. 配置 Vim 高亮显示 * 五、编译运行C++代码 前言 * 在前面的博客里,我们讲解了什么是操作系统,以及它的历史,接下来我们开始构建Linxu环境 * 本次博客将带领大家完成 CentOS 9.0 的安装,

By Ne0inhk
Flutter 三方库 opml 的鸿蒙化适配指南 - 支持大容量订阅源解析、符合 OPML 2.0 规范与 RSS 管理器核心适配

Flutter 三方库 opml 的鸿蒙化适配指南 - 支持大容量订阅源解析、符合 OPML 2.0 规范与 RSS 管理器核心适配

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 opml 的鸿蒙化适配指南 - 支持大容量订阅源解析、符合 OPML 2.0 规范与 RSS 管理器核心适配 前言 在进行 Flutter for OpenHarmony 的阅读类、播客类或 RSS 订阅类应用开发时,支持标准的 OPML(Outline Processor Markup Language)导入与导出是必选功能。opml 库是一个专门用于解析和生成 OPML 文件的 Dart 库。本文将探讨如何在鸿蒙系统下,利用该库高效管理用户的订阅树结构。 一、原理解析 / 概念介绍 1.1 基础原理 OPML 本质上是一种基于

By Ne0inhk
【高级终端Termux】在安卓手机/平板上使用Termux 搭建 Debian 环境并运行 PC 级 Linux 应用教程(含安装WPS,VS Code)

【高级终端Termux】在安卓手机/平板上使用Termux 搭建 Debian 环境并运行 PC 级 Linux 应用教程(含安装WPS,VS Code)

Termux 搭建 Debian 环境并运行 PC 级 Linux 应用教程 一、前言 1. 背景 众所周知,最新搭载澎湃OS和鸿蒙OS的平板都内置了PC级WPS,办公效率直接拉满(板子终于从“泡面盖”升级为“生产力”了)。但问题来了:如果不是这两个系统,难道我们只能继续用平板盖泡面吗?当然不是!折腾了很长时间后,总算找到了一个好玩的东西:高级终端Termux 。现在,不仅能随时随地用WPS改文档,还能VSCode优雅地敲代码,再也不用背着电脑乱跑了。 由于每次搭建环境时都要去不同的平台找不同功能,有时还找不到,所以我决定自己写一篇博客,方便自己以后再搭建时直接“Ctrl C + Ctrl V”,顺便分享给有同样需求的小伙伴们。话不多说,直接开整! 2. 准备工作 * 一部安卓手机:性能越好,折腾起来越顺畅。 * Termux 应用: 不想去F-droid下载的看过来

By Ne0inhk