目录
- 引言
- 1. SpringSecurity
- 1.1 SpringSecurity简介
- 1.2 SpringSecurity工作原理
- 1.3.特点
- 2. SpringSecurity的快速使用
- 总结
引言
SpringSecurity作为Spring框架中的一个重要组成部分,扮演着保护应用程序安全的重要角色。本文将深入探讨SpringSecurity的原理、使用方法以及快速实践,帮助读者全面了解和掌握SpringSecurity的相关知识。
1. SpringSecurity
1.1 SpringSecurity简介
Spring Security
是一个基于Spring
框架的安全性框架,可用于对Java应用程序进行身份验证、授权和其他安全性功能的添加。它不仅可以对Web应用程序进行保护,还可以保护非Web环境下的应用程序,如远程服务和命令行应用程序等。Spring Security
提供了一系列可插拔的安全性特性,如基于标记的身份验证、权限控制、单点登录、密码加密等。它还支持多种安全性协议和标准,如OAuth
、SAML
、OpenID
等,可与各种身份提供商集成。## 1.2 SpringSecurity核心原理
深入探讨SpringSecurity的核心原理,包括安全过滤器链、认证管理器、用户详情服务等关键组件的工作原理和作用,帮助读者理解SpringSecurity的内部机制。
1.2 SpringSecurity工作原理
权限框架一般包含两大核心模块:认证(Authentication)和鉴权(Authorization)。
- 认证:认证模块负责验证用户身份的合法性,生成认证令牌,并保存到服务端会话中(如TLS)。
- 鉴权:鉴权模块负责从服务端会话内获取用户身份信息,与访问的资源进行权限比对。
核心组件介绍:
AuthenticationManager
:管理身份验证,可以从多种身份验证方案中选择一种。Authentication
:用于验证用户的身份。SecurityContextHolder
:用于管理SecurityContext
的ThreadLocal
,以便在整个请求上下文中进行访问,方便用户访问。AccessDecisionManager
:负责对访问受保护的资源的请求进行决策(即决定是否允许用户访问资源)AccessDecisionVoter
:是AccessDecisionManager的实现组件之一,它用于对用户请求的访问受保护的资源所需要的角色或权限进行投票。ConfigAttribute
:用于表示受保护资源或URL需要的访问权限,它可以理解为是访问控制策略的一部分
1.3.特点
- 兼容性强:
Spring Security
是一个流行的开源框架,它可以与Spring应用程序完美集成。由于它的兼容性很好,因此可以非常方便地使用它保护Web应用程序。 - 功能强大:
Spring Security
具备众多功能,包括注销、登录、角色、权限、令牌、XSS
防御、CSRF
防御等等。它还支持各种身份验证、角色和权限管理方式,如基于表单的认证、基于记住我功能的认证以及OAuth
认证等等。 - 安全可靠:
Spring Security
具有极高的安全性,它使用最新的安全标准和协议来保护Web应用程序。Spring Security
采用安全性分层的策略来保护应用程序中的各个层,例如Web
层、Service
层、DAO
层等等。除此之外,Spring Security
还支持自定义安全策略和事件响应,从而使得开发者可以根据应用程序需求定制安全保护。 - 易于使用:
Spring Security
提供了一种高度简化的方式来保护Web应用程序。它使用简单的标签和安全注解来添加安全保护,从而使得开发者可以基本不需要手动编写代码就可以完成安全保护。 - 社区广泛:
Spring Security
是一个著名的开源框架,因此它有一个庞大的用户社区。这个社区不仅提供了大量的文档、示例和教程,而且还会解答开发者的问题、修复框架中的BUG等等。这为开发者提供了无限的支持和帮助,从而可以使用Spring Security
更加自信。
2. SpringSecurity的快速使用
基于SpringBoot创建项目
pom文件配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
配置application.yml
文件:
spring:
freemarker:
# 设置freemarker模板后缀
suffix: .ftl
# 设置freemarker模板前缀
template-loader-path: classpath:/templates/
enabled: true
用户登录Controller页面
package com.yuan.springsecurity1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
@RequestMapping("/userLogin")
public String userLogin(String username, String password) {
System.out.println("username=" + username + ",password=" + password);
return "index";
}
@RequestMapping("/admin/toAddUser")
public String toAddUser() {
return "admin/addUser";
}
@RequestMapping("/admin/toListUser")
public String toListUser() {
return "admin/listUser";
}
@RequestMapping("/admin/toResetPwd")
public String toResetPwd() {
return "admin/resetPwd";
}
@RequestMapping("/admin/toUpdateUser")
public String toUpdateUser() {
return "admin/updateUser";
}
@RequestMapping("/user/toUpdatePwd")
public String toUpdatePwd() {
return "user/updatePwd";
}
@RequestMapping("/noAccess")
public String noAccess() {
return "accessDenied";
}
}
输入http://localhost:8080进入
项目启动默认用户user,密码在启动程序打印上面
创建SecurityConfig配置类
package com.yuan.springsecurity1.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
//开启SpringSecurity的默认行为
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public PasswordEncoder bcryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(){
UserDetails admin = User.withUsername("admin")
.password(bcryptPasswordEncoder().encode("123456"))
.roles("ADMIN", "USER").build();
UserDetails user = User.withUsername("user")
.password(bcryptPasswordEncoder().encode("123456"))
.roles("USER").build();
return new InMemoryUserDetailsManager(admin,user);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception{
http.authorizeRequests()
// 开放接口访问权限,不需要登录就可以访问
.antMatchers("/toLogin").permitAll()
//访问路径有admin的方法时,需要有ADMIN的身份
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("ADMIN","USER")
// 其余所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.formLogin()
// 设置登录页面的 URL
.loginPage("/toLogin")
// 设置登录请求的 URL,即表单提交的 URL
.loginProcessingUrl("/userLogin")
// 设置登录表单中用户名字段的参数名,默认为username
.usernameParameter("username")
// 设置登录表单中密码字段的参数名,默认为password
.passwordParameter("password")
.and()
.exceptionHandling().accessDeniedPage("/noAccess")
.and()
.logout()
// 设置安全退出的URL路径
.logoutUrl("/logout")
// 设置退出成功后跳转的路径
.logoutSuccessUrl("/toLogin") ;
http.csrf().disable();
return http.build();
}
}
配置好后,启动项目,访问http://localhost:8080/toLogin
输入admin,123456,因为设置了admin可以访问所有的,下面点击事件都能用
点击安全退出,session保存的清除
user登录,没有管理员权限,新增用户
总结
通过本文的学习,读者将全面了解SpringSecurity的原理和使用方法,掌握快速实践SpringSecurity的技能,并能够根据实际需求定制化安全策略,构建安全可靠的应用程序。