1,springSecurity(安全)
一个安全的框架,其实通过过滤器和拦截器也可以实现
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。
Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求
在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。
Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!
记住几个类:
**WebSecurityConfigurerAdapter:**自定义Security策略
**AuthenticationManagerBuilder:**自定义认证策略
**@EnableWebSecurity:**开启WebSecurity模式 @Enablexxx 开启某个功能
Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。
“认证”(Authentication)
身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。
身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。
“授权” (Authorization)
授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。
这个概念是通用的,而不是只在Spring Security 中存在。
2,使用
2,1导入依赖
<!--SpringSecurity -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2,2创建配置类
新建一个配置文件,并且继承 WebSecurityConfigurerAdapter,并且要添加@EnableWebSecurity注解
@EnableWebSecurity//表示开启Security
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}
一般放在config包下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9HspdHiE-1668096107858)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220917205016786.png)]
2,3定义授权的规则
@Override//重写方法
//这个方法主要用于设置权限分配规则,链式编程
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问,功能页需要对应权限
http.authorizeRequests()//设置权限分配规则
.antMatchers("/").permitAll()//意思:‘/’请求全部用户都可以访问
.antMatchers("/level1/**").hasAnyRole("vip1")//意思:"/level1"下面的全部请求vip1权限可以访问
.antMatchers("/level2/**").hasAnyRole("vip2")//意思:"/level2"下面的全部请求vip2权限可以访问
.antMatchers("/level3/**").hasAnyRole("vip3");//意思:"/level3"下面的全部请求vip3权限可以访问
//当没有权限时会默认跳到登录页面(登录页名字要为login)
http.formLogin();
}
测试一下:发现除了首页都进不去了!因为我们目前没有登录的角色,因为请求需要登录的角色拥有对应的权限才可以!
添加 http.formLogin();后,测试发现没有权限的时候,会跳转到登录的页面:
2,4认证权限
还是这个类中
重写configure(AuthenticationManagerBuilder auth)方法
//定义分配权限
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//在内存中定义,也可以在jdbc中去拿....(是另一个方法)
auth.inMemoryAuthentication()
.withUser("kuangshen").password("123456").roles("vip2","vip3")
.and()
.withUser("root").password("123456").roles("vip1","vip2","vip3")
.and()
.withUser("guest").password("123456").roles("vip1");
}
/*
auth.inMemoryAuthentication() 在内存中取用户数据
.withUser("用户名") 设置用户名
.password("密码") 设置密码
.roles("之前设置的权限名"。。。) 分配权限
.and() 连接下一个用户的信息
*/
传递数据库数据的用户
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JzBTmwtT-1668096107859)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220918181744298.png)]
如果报错:
原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码
//定义认证规则
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//在内存中定义,也可以在jdbc中去拿....
//Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
//要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
//spring security 官方推荐的是使用bcrypt加密方式。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");
}
/*
passwordEncoder(new BCryptPasswordEncoder()) 定义密码加密格式,new的加密格式有很多
BCryptPasswordEncoder().encode("密码") new的什么格式就用什么格式加密
*/
2,5 注销
http.logout()//开启注销功能
//注销按钮发送一个‘/logout’请求
//注销后跳到指定路径,源码中有方法
http.logout().logoutSuccessUrl("指定路径")//注销成功后跳到指定页面
2,6根据不同权限展示不同页面
重点!!!
这个功能很重要
sec:authorize=“isAuthenticated()”:是否认证登录!来显示不同的页面
步骤:
1,导包(thymeleaf----security整合包)
<!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
2,导入命名空间
sec命名空间
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
注意:这里可能会产生一些问题你可以通过降版本尝试解决
3,使用
//常用方法
sec:authorize="isAuthenticated()" //用户有权限返回true
sec:authentication="name" //获取name参数的数据
sec:authentication="principal.表单参数名" //获取表单传递的数据
principal.authorities //获取权限的名称
sec:authorize="hasRole('权限名1','2'..)" //判断当前的权限是否有这个权限直接加在想要设置权限的标签内即可
hasRole('权限名1','2'..) 是根据不同的权限选择是否展示这个标签[1~n]
isAuthenticated()是根据是否有权限选择是否展示这个标签[0~n]
如果注销404了,就是因为它默认防止csrf跨站请求伪造,因为会产生安全问题,我们可以将请求改为post表单提交,或者在spring security中关闭csrf功能;我们试试:在 配置中增加 http.csrf().disable();
configure这个方法中
//在security的配置类中写
http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
2,7 记住我和首页定制
记住我功能
//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
//记住我
http.rememberMe();
//可自定义标签
<input type="checkbox" name="remember"> 记住我//前端添加一个选择框
http.rememberMe().rememberMeParameter("remember");//添加一个方法,参数为选择框的name属性
}
定制登录页
方式一:
//这种方式请求需要一致
1,在刚才的登录页配置后面指定 loginpage(配置类中)
http.formLogin().loginPage("/toLogin");
2,然后前端也需要指向我们自己定义的 login请求(首页中)
<a class="item" th:href="@{/toLogin}">
<i class="address card icon"></i> 登录
</a>
//这是登录认证的请求,表单的请求不走controller
3,我们登录,需要将这些信息发送到哪里,我们也需要配置,login.html 配置提交请求及方式,方式必须为post:
<form th:action="@{/toLogin}" method="post">
//这种方式,controller,首页,登录页,配置类中的请求都要一致
当你在首页发送登录请求,会通过controller跳到登录页,然后在登录页中发送登录请求虽然没有这个请求,但是只要这4个请求一致即可跳转。
//登录(自己写的页面)和登录认证(security自带的认证页面)的页面绑定为一个页面
图示解析:
方式二:
可以让这4个的请求不一致
两两对应:
登录认证的请求为另一个请求(表单发出的请求)
http.formLogin()
.usernameParameter("name") //表单中账号的name属性(默认username,程序员改了名字使用)
.passwordParameter("pwd") //表单中密码的name属性(默认password,程序员改了名字使用)
.loginPage("/toLogin"); //自己写的登录页
.loginProcessingUrl(表单请求); //表单提交的请求
3,security的作用
代替过滤器,拦截器
分配权限,定义权限规则,传递表单数据,防止跨站攻击,根据权限显示不同页面,定制首页,记住我