续 Spring 安全框架
密码加密的实现
上次课讲解了密码加密的概念
介绍了bcrypt密码加密的算法
下面我们通过一个测试,演示这个算法
// 声明密码加密操作对象
PasswordEncoder encoder=new BCryptPasswordEncoder();
// 加密测试
@Test
public void pwd(){
String str="123456";
// 执行加密,使用encode方法参数是要加密的字符串,返回值是加密结果
String pwd= encoder.encode(str);
System.out.println(pwd);
//$2a$10$kVuKchYUN92TGcQb./H.iOHCT8LOIho12bI1OTb5xPTassynjdsES
}
运行测试方法,能够得到加密结果
我们发现每次加密结果是不同的
因为如果每次加密结果时固定的,反而容易被人破解,并不安全
bcrypt加密算法采用了"随机加盐"技术,每次加密结果不同,提高了安全等级
下面我们来测试,加密得到的字符串,能不能正确的验证成功
"验证"指判断当前加密字符串是不是指定字符串生成的
// 验证操作
@Test
public void match(){
// 验证一个字符串是否能够加密为指定的加密结果
// 方法matches([原字符串],[加密字符串])返回值是boolean类型
// 返回值为真表示验证通过,返回值为假表示验证失败
boolean b=encoder.matches("123456",
"$2a$10$kVuKchYUN92TGcQb./H.iOHCT8LOIho12bI1OTb5xPTassynjdsE");
System.out.println("验证结果为:"+b);
}
上面的测试如果运行输出验证通过(true),表示字符串和加密结果匹配
否则会输出false
下面将我们的application.properties配置文件中的用户密码设置为加密的
# Spring-Security自定义登录用户名和密码的配置
spring.security.user.name=admin
spring.security.user.password={bcrypt}$2a$10$kVuKchYUN92TGcQb./H.iOHCT8LOIho12bI1OTb5xPTassynjdsES
{bcrypt}是"算法id"的声明定义
表示后面的字符串是由bcrypt算法加密得来的
登录时会按照相同的算法来验证
Spring-Security配置登录与权限管理
上面章节中我们将登录用户信息保存在application配置文件中
实际登录时,一定是从数据库来获得用户信息的,所以登录一定会编写在java代码中
我们学习如何在java配置类中配置一个用户的登录,顺便演示用户的权限管理功能
portal项目中创建一个security包
这个包中创建SecurityConfig类,进行配置代码如下
// SpringBoot启动时扫描到@Configuration标记的类,会自动加载其中的配置
// 所有SpringBoot框架环境下@Configuration必须写才能配置生效
@Configuration
// 启动Spring-Security配置的注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// WebSecurityConfigurerAdapter是我们需要基础的父类
// 这个父类提供了配置Spring-Security运行的基本方法
// 我们要想修改配置的话,重写它的方法即可
// 下面我们就配置一个可以登录的用户
// 一旦重写这个方法,配置文件中的admin就失效了
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 删除原有的super调用
// 在代码中配置一个等于用户
// inMemory表示在内存中保存一个用户
auth.inMemoryAuthentication()
.withUser("tom")
.password("{bcrypt}$2a$10$ELGiEhKyLlO9r3.WVOkHDe16JTCKCErcABhElD5CF7ZwQ.Hm6sVRW")
.authorities("answer");
// 我们配置了一个可以登录的用户
// 用户名tom 密码 888888
// 在代码最后一行,我们授予了当前tom用户answer的授权\资格
// 这个授权或资格可以访问需要对应授权的控制器方法
}
}
重启服务
登录tom
登录成功后可以访问项目的大部分资源
但是如果有控制器方法需要特殊授权才能执行
运行前Spring-Security会验证当前用户是否具有这个资格
我们在UserController中编写两个需要不同授权才能访问的方法代码如下
@GetMapping("/answer")
// 下面的注解规定当前用户必须包含answer授权
// 才能访问下面的控制方法
@PreAuthorize("hasAuthority('answer')")
public String answer(){
return "允许回答问题!";
}
@GetMapping("/delete")
@PreAuthorize("hasAuthority('delete')")
public String delete(){
return "允许删除回答!";
}
重启服务
tom用户具有answer授权
所以可以访问/answer方法
但是访问/delete方法时返回403错误,表示没有权限访问
这样就能显示某些用户访问某些资源
如果想让一个用户具有多个授权,可以改写登录配置如下
String[] as={"answer","delete"};
// inMemory表示在内存中保存一个用户
auth.inMemoryAuthentication()
.withUser("tom")
.password("{bcrypt}$2a$10$ELGiEhKyLlO9r3.WVOkHDe16JTCKCErcABhElD5CF7ZwQ.Hm6sVRW")
.authorities(as);
再重启服务,登录tom
就可以访问/answer和/delete两个方法了!
用户与权限
上面章节,我们学习了定义一个用户的登录,并且设置一个用户具有的授权
我们在登录当前数据库中用户时,又如何确定这个用户的授权呢?
现在登录需要的信息有
1.用户名
2.密码(加密的)
3.用户的所有权限
上面的信息都保存在数据库中,用户名和密码保存在user表里
但是用户的授权(权限)是需要相对复杂的查询才能查询出来的
上的5张表表示的是用户\角色\权限的关系
我们需要根据用户的id查询出这个用户具有哪些角色
在根据用户的角色查询出它的所有权限
他们之前的关系表有user_role和role_permission
英文
Enable:启用\启动
Global:全局\全球
Adapter:适配器
Configurer:配置
Authentication:授权
今后几乎所有auth开头的单词都是授权的意思,只是不同的词性
Memory:记忆\计算机中就是内存
学校中的用户和权限
用户 中间表 角色 中间表 权限
杨过 学生 签到
令狐冲 任课老师 成绩管理
欧阳锋 班主任 学生管理
乔峰 年级组长 课程管理
段誉 教导主任 教职工管理
洪七公 校长 学校倒闭
表与表之间的关系
1.一对一
2.一对多(多对一):
班级和学生
部门和员工
特征:在多(学生表)的一方,保存一个一的一方(班级表)的id列
一对多是所有关系中最常见的关系
3.多对多
传统义务教育阶段的老师和班级
一个老师给多个班级讲课
一个班级被多个老师教
特征:在两张表之间,创建一个关系表
关系表中保存班级和老师的关系