跳到主要内容
Spring Boot 安全认证与授权 | 极客日志
Java java
Spring Boot 安全认证与授权 综述由AI生成 Spring Boot 中集成 Spring Security 进行安全认证与授权的完整流程。内容包括 Spring Security 的定义、特点及与 Spring Boot 的集成步骤。详细讲解了基于内存和数据库两种认证方式,以及基于角色和权限的授权策略。通过实际代码示例展示了用户登录、登出、角色管理及权限控制的实现方法,适用于构建安全的 Java Web 应用。
时间旅人 发布于 2026/3/30 更新于 2026/5/24 24 浏览Spring Boot 安全认证与授权
22.1 学习目标与重点提示
学习目标 :掌握 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 Boot、Spring Cloud 等整合
小结 :Spring Security 的特点包括全面性、可扩展性、易用性、整合性。
22.3 Spring Boot 与 Spring Security 的集成
22.3.1 集成 Spring Security 的步骤
步骤 :
创建 Spring Boot 项目
添加所需的依赖
配置 Spring Security
创建用户服务类
创建控制器类
测试应用
示例 :pom.xml 文件中的依赖
<dependencies >
<dependency >
<groupId > org.springframework.boot</ >
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-test
test
groupId
<artifactId >
</artifactId >
</dependency >
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
</dependency >
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<scope >
</scope >
</dependency >
</dependencies >
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin" ).password("admin123" ).roles("ADMIN" )
.and()
.withUser("user" ).password("user123" ).roles("USER" );
}
@Override
protected void configure (HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**" ).hasRole("ADMIN" )
.antMatchers("/user/**" ).hasRole("USER" )
.antMatchers("/" ).permitAll()
.and()
.formLogin().loginPage("/login" ).permitAll()
.and()
.logout().permitAll();
}
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SecurityController {
@GetMapping("/")
public String index () { return "index" ; }
@GetMapping("/login")
public String login () { return "login" ; }
@GetMapping("/user")
public String user () { return "user" ; }
@GetMapping("/admin")
public String admin () { return "admin" ; }
}
视图模板文件(src/main/resources/templates/index.html)
<!DOCTYPE html >
<html lang ="zh-CN" >
<head >
<meta charset ="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 >
<div class ="container" >
<h1 > 首页</h1 >
<a href ="/login" > 登录</a >
<a href ="/user" > 用户页面</a >
<a href ="/admin" > 管理员页面</a >
</div >
</body >
</html >
视图模板文件(src/main/resources/templates/login.html)
<!DOCTYPE html >
<html lang ="zh-CN" >
<head >
<meta charset ="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 >
<div class ="container" >
<h1 > 登录</h1 >
<form th:action ="@{/login}" method ="post" >
<label for ="username" > 用户名:</label >
<input type ="text" id ="username" name ="username" required >
<label for ="password" > 密码:</label >
<input type ="password" id ="password" name ="password" required >
<button type ="submit" > 登录</button >
</form >
<a href ="/" > 返回首页</a >
</div >
</body >
</html >
视图模板文件(src/main/resources/templates/user.html)
<!DOCTYPE html >
<html lang ="zh-CN" >
<head >
<meta charset ="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 >
<div class ="container" >
<h1 > 用户页面</h1 >
<a href ="/" > 返回首页</a >
<a href ="/logout" > 登出</a >
</div >
</body >
</html >
视图模板文件(src/main/resources/templates/admin.html)
<!DOCTYPE html >
<html lang ="zh-CN" >
<head >
<meta charset ="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 >
<div class ="container" >
<h1 > 管理员页面</h1 >
<a href ="/" > 返回首页</a >
<a href ="/logout" > 登出</a >
</div >
</body >
</html >
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import java.util.Base64;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SpringSecurityApplicationTests {
@LocalServerPort private int port;
@Autowired private TestRestTemplate restTemplate;
@Test void contextLoads () {}
@Test void testIndexPage () {
String response = restTemplate.getForObject("http://localhost:" + port + "/" , String.class);
assertThat(response).contains("首页" );
}
@Test void testUserPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/user" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testUserPageWithUserAuthentication () {
String credentials = "user:user123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(headers);
ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/user" , HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).contains("用户页面" );
}
@Test void testAdminPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/admin" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testAdminPageWithAdminAuthentication () {
String credentials = "admin:admin123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(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 的认证
22.4.1 基于内存的认证 定义 :基于内存的认证是指 Spring Security 提供的一种认证方式。
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin" ).password("admin123" ).roles("ADMIN" )
.and()
.withUser("user" ).password("user123" ).roles("USER" );
}
@Override
protected void configure (HttpSecurity http) throws Exception {
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 提供的一种认证方式。
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-security</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-data-jpa</artifactId >
</dependency >
<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 >
import javax.persistence.*;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String role;
public User () {}
public User (String username, String password, String role) {
this .username = username;
this .password = password;
this .role = role;
}
public Long getId () { return id; }
public void setId (Long id) { this .id = id; }
public String getUsername () { return username; }
public void setUsername (String username) { this .username = username; }
public String getPassword () { return password; }
public void setPassword (String password) { this .password = password; }
public String getRole () { return role; }
public void setRole (String role) { this .role = role; }
@Override
public String toString () {
return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", role='" + role + '\'' + '}' ;
}
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository <User, Long> {
User findByUsername (String username) ;
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername (String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null ) {
throw new UsernameNotFoundException ("用户不存在:" + username);
}
List<GrantedAuthority> authorities = new ArrayList <>();
authorities.add(new SimpleGrantedAuthority ("ROLE_" + user.getRole()));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getUsername())
.password(user.getPassword())
.authorities(authorities)
.build();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
public PasswordEncoder passwordEncoder () {
return NoOpPasswordEncoder.getInstance();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean () throws Exception {
return super .authenticationManagerBean();
}
@Override
protected void configure (HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**" ).hasRole("ADMIN" )
.antMatchers("/user/**" ).hasRole("USER" )
.antMatchers("/" ).permitAll()
.and()
.formLogin().loginPage("/login" ).permitAll()
.and()
.logout().permitAll();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class SecurityController {
@Autowired
private UserRepository userRepository;
@GetMapping("/")
public String index () { return "index" ; }
@GetMapping("/login")
public String login () { return "login" ; }
@GetMapping("/user")
public String user () { return "user" ; }
@GetMapping("/admin")
public String admin () { return "admin" ; }
@PostMapping("/register")
public String registerUser (String username, String password, String role) {
User user = new User (username, password, role);
userRepository.save(user);
return "redirect:/login" ;
}
}
视图模板文件(src/main/resources/templates/register.html)
<!DOCTYPE html >
<html lang ="zh-CN" >
<head >
<meta charset ="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 >
<div class ="container" >
<h1 > 注册</h1 >
<form th:action ="@{/register}" method ="post" >
<label for ="username" > 用户名:</label >
<input type ="text" id ="username" name ="username" required >
<label for ="password" > 密码:</label >
<input type ="password" id ="password" name ="password" required >
<label for ="role" > 角色:</label >
<select id ="role" name ="role" required >
<option value ="USER" > 用户</option >
<option value ="ADMIN" > 管理员</option >
</select >
<button type ="submit" > 注册</button >
</form >
<a href ="/" > 返回首页</a >
</div >
</body >
</html >
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import java.util.Base64;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SpringSecurityApplicationTests {
@LocalServerPort private int port;
@Autowired private TestRestTemplate restTemplate;
@Test void contextLoads () {}
@Test void testIndexPage () {
String response = restTemplate.getForObject("http://localhost:" + port + "/" , String.class);
assertThat(response).contains("首页" );
}
@Test void testUserPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/user" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testUserPageWithUserAuthentication () {
String credentials = "user:user123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(headers);
ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/user" , HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).contains("用户页面" );
}
@Test void testAdminPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/admin" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testAdminPageWithAdminAuthentication () {
String credentials = "admin:admin123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(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 的授权
22.5.1 基于角色的授权 定义 :基于角色的授权是指 Spring Security 提供的一种授权方式。
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin" ).password("admin123" ).roles("ADMIN" )
.and()
.withUser("user" ).password("user123" ).roles("USER" );
}
@Override
protected void configure (HttpSecurity http) throws Exception {
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 提供的一种授权方式。
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin" ).password("admin123" ).roles("ADMIN" )
.and()
.withUser("user" ).password("user123" ).roles("USER" );
}
@Override
protected void configure (HttpSecurity http) throws Exception {
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 的应用场景非常广泛,如:
实现用户的登录与登出
实现用户的角色管理
实现用户的权限管理
实现系统的安全审计
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@SpringBootApplication
public class SecurityApplication {
public static void main (String[] args) {
SpringApplication.run(SecurityApplication.class, args);
}
}
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin" ).password("admin123" ).roles("ADMIN" )
.and()
.withUser("user" ).password("user123" ).roles("USER" );
}
@Override
protected void configure (HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**" ).hasRole("ADMIN" )
.antMatchers("/user/**" ).hasRole("USER" )
.antMatchers("/" ).permitAll()
.and()
.formLogin().loginPage("/login" ).permitAll()
.and()
.logout().permitAll();
}
}
@Controller
class SecurityController {
@GetMapping("/")
public String index () { return "index" ; }
@GetMapping("/login")
public String login () { return "login" ; }
@GetMapping("/user")
public String user () { return "user" ; }
@GetMapping("/admin")
public String admin () { return "admin" ; }
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SecurityApplicationTests {
@LocalServerPort private int port;
@Autowired private TestRestTemplate restTemplate;
@Test void contextLoads () {}
@Test void testIndexPage () {
String response = restTemplate.getForObject("http://localhost:" + port + "/" , String.class);
assertThat(response).contains("首页" );
}
@Test void testUserPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/user" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testUserPageWithUserAuthentication () {
String credentials = "user:user123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(headers);
ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/user" , HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).contains("用户页面" );
}
@Test void testAdminPageWithoutAuthentication () {
ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:" + port + "/admin" , Map.class);
assertThat(response.getStatusCodeValue()).isEqualTo(302 );
}
@Test void testAdminPageWithAdminAuthentication () {
String credentials = "admin:admin123" ;
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
HttpHeaders headers = new HttpHeaders ();
headers.add("Authorization" , "Basic " + base64Credentials);
HttpEntity<String> entity = new HttpEntity <>(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 Boot 与 Spring Security 的应用场景非常广泛,需要根据实际问题选择合适的安全框架。
总结 本章我们学习了 Spring Boot 安全认证与授权,包括 Spring Security 的定义与特点、Spring Boot 与 Spring Security 的集成、配置、认证、授权及实际应用场景,学会了在实际开发中处理安全认证与授权问题。其中,Spring Security 的定义与特点、Spring Boot 与 Spring Security 的集成、配置、认证、授权及实际应用场景是本章的重点内容。从下一章开始,我们将学习 Spring Boot 的其他组件、微服务等内容。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online