Spring Security
1. 简介
Spring Security是Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。
一般来说中大型的项目都是使用SpringSecurity来做安全框架,小项目用Shiro的比较多,因为相比与SpringSecurity,Shiro的上手更加的简单。
一般Web应用都需要进行认证和授权。
认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户
授权:经过认证后判断当前用户是否有权限进行某个操作
- 功能权限
- 访问权限
- 菜单权限
- ..拦截器、过滤器:大量原生代码~
认证和授权是SpringSecurityf作为安全框架的核心功能。
先认识几个类,有个印象:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
2. 快速入门
1.1 准备工作
-
首先搭建一个简单的SpringBoot工程
-
设置父工程,添加依赖
<parent> <version>2.7.4</version> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
-
创建启动类
@SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication.run(SecurityApplication.class,args); } }
-
创建Controller
package com.mark.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName HelloController * @Description TODO * @Author Mark * @Date 2022/9/28 20:11 * @Version 1.0 */ @Controller public class RouterController { @RequestMapping({"/", "/index"}) public String index() { return "index"; } @RequestMapping("/toLogin") public String toLogin() { return "views/login"; } @RequestMapping("/level1/{id}") public String level1(@PathVariable("id") int id) { return "views/level1/" + id; } @RequestMapping("/level2/{id}") public String level2(@PathVariable("id") int id) { return "views/level2/" + id; } @RequestMapping("/level3/{id}") public String level3(@PathVariable("id") int id) { return "views/level3/" + id; } }
-
1.2 初识SpringSecurity
-
导包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
-
配置类Security Java Configuration:
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... } }
-
自定义Security授权策略:
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //链式编程 //首页所有人可以访问,功能页只有有权限的人才能访问 //请求授权的规则 http.authorizeRequests() .antMatchers("/").permitAll() //只有vip1用户可访问/level1/** .antMatchers("/level1/**").hasRole("vip1") //只有vip2用户可访问/level2/** .antMatchers("/level2/**").hasRole("vip2") //只有vip3用户可访问/level3/** .antMatchers("/level3/**").hasRole("vip3"); //没有权限默认跳转到登录页面:/login //http.formLogin(); //登录页面跳转到/toLogin http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login"); } }
authorizeRequests():认证请求
antMatchers():添加地址
permitAll():所有人都可访问
hasRole():只有xx用户可访问
loginProcessingUrl默认的用户名和密码为username和password,若前端字段非username和password,则接受不到数据,因此需添加以下方法实现对应字段接收:
http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login");
-
自定义认证策略:
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //认证,SpringBoot 2.1.x 可以直接使用 //jdbc认证:auth.jdbcAuthentication() //从内存中认证,正常应该从数据库中读取 auth.inMemoryAuthentication() .withUser("Mark").password("123456").roles("vip1","vip2") .and() .withUser("root").password("123456").roles("vip1","vip2","vip3") .and() .withUser("Java").password("123456").roles("vip1"); }
withUser():添加用户名为xx的用户
password():设置密码
roles("vip1","vip2","vip3"):设置用户权限类别
-
SpringBoot 2.1.x 可以直接使用,在SpringSecurity 5.0+中,新增了很多加密方式,不能使用明文密码,要使用密码编码:PasswordEncoder
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("Mark").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2") .and() .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3") .and() .withUser("Java").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
-
1.3 注销
-
在configure(HttpSecurity http)中添加
http.logout();
即可。访问的是/logout端口 -
logout的其他功能
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3"); http.formLogin(); //防止网站攻击 //关闭防止跨站请求的功能,登录失败可能存在的原因 http.csrf().disable(); //开启注销功能:/logout http.logout() //清空所有的cookie和session .deleteCookies("remove").invalidateHttpSession(true); //注销后跳转到首页 .logoutSuccessUrl("/"); }
1.4 记住登录状态功能开启
-
在configure(HttpSecurity http)中添加
http.rememberMe();
即可- 会保存cookie,默认保存两周
-
接收前端记住登陆状态按钮name参数:
http.rememberMe().rememberMeParameter("remember");
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!