目录
SpringSecurity
1、简介
1.1、引言
在 Web 开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。如果在应用开发的后期才考虑安全的问题,就可能陷入一个两难的境地:一方面,应用存在严重的安全漏洞,无法满足用户的要求,并可能造成用户的隐私数据被攻击者窃取;另一方面,应用的基本架构已经确定,要修复安全漏洞,可能需要对系统的架构做出比较重大的调整,因而需要更多的开发时间,影响应用的发布进程。因此,从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。
1.2、介绍
市面上常用
- Shiro
- Spring Security
这里需要阐述一下的是,每一个框架的出现都是为了解决某一问题而产生了,那么Spring Security框架的出现是为了解决什么问题呢?
Spring Security
- Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权
- 与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求
2、设计模式
适配器模式
建造者模式
3、注解
@EnableWebSecurity
4、功能
4.1、准备工作
引入Security依赖
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--security-thymeleaf-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
编写配置类
- WebSecurityConfigurerAdapter
- AuthenticationManagerBuilder
实现具体功能
4.2、授权和认证
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
//设置权限(认证)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//设置没有权限,会让我们跳转到Security默认的登录页面
http.formLogin();
}
//授权
//自定义授权,可以到内存中取,也可以到数据库中取
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("mtf").password("123456").roles("vip1")
.and()
.withUser("root").password("123456").roles("vip1","vip2","vip3");
}
}
问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VEu2B6NG-1663054903769)(security笔记图片/认证和授权问题.png)]
- 我们需要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码
更改后
//Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
//要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
//spring security 官方推荐的是使用bcrypt加密方式。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("mtf").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3");
}
- 更改后,测试成功!
4.3、注销和权限控制
1、注销
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//设置没有权限,会让我们跳转到Security默认的登录页面
http.formLogin();
//注销
http.logout().logoutSuccessUrl("/");
}
2、权限控制
权限控制问题引入:不同权限的用户可以看到不一样的界面
比如mtf这个用户,它只有 vip1功能,那么登录则只显示这一个功能,而vip2和vip3的功能菜单不显示!这个就是真实的网站情况了!该如何做呢?
-
导入security和thymeleaf整合依赖
<!--security-thymeleaf--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <!--这里写了版本号出现500错误 <version>3.1.0.M1</version>--> </dependency>
-
在前端使用
<sec:xx/>
标签来进行判断“动态显示菜单”<div sec:authorize="!isAuthenticated()"> <a class="item" th:href="@{/login}"> <i class="address card icon"></i> 登录 </a> </div> <div sec:authorize="isAuthenticated()"> <!--如果登录:用户名,注销--> <a class="item"> 用户名:<span sec:authentication="name"></span> </a> </div> <div sec:authorize="isAuthenticated()"> <!--注销--> <a class="item" th:href="@{/logout}"> <i class="sign-out icon"></i> 注销 </a> </div> <div class="column" sec:authorize="hasRole('vip1')"> </div> <div class="column" sec:authorize="hasRole('vip2')"> </div> <div class="column" sec:authorize="hasRole('vip3')"> </div>
4.4、记住我和页面定制
1、记住我(Cookie)
开启默认的记住我功能
http.rememberMe();
2、定制页面(登录页)
loginPage(“/toLogin”)是访问到登录页
loginProcessingUrl(“/login”)是处理登录请求,这里的/login是security的内置请求,提交表单方式为post