新建个SpringBoot工程,写三个controller,里面有三个接口:
//学生
@RestController
@RequestMapping("/student")
public class StudentController {
@GetMapping("/query")
public String queryInfo(){
return "this is a student,9527";
}
}
//老师
@RestController
@RequestMapping("/teacher")
public class TeacherController {
@GetMapping("/query")
public String queryInfo(){
return "this is a teacher,Mr.L";
}
}
//管理员
@RestController
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/query")
public String queryInfo(){
return "this is a administrator, root";
}
}
启动程序,此时不论是谁,访问这三个接口资源,都能成功返回信息。
curl -X GET localhost:9527/teacher/query
即没有加入安全框架的代码程序,默认所有资源均不受保护,可被随意访问,因此,需要集成安全框架。
认证:
认证是为了保护系统的隐私数据与资源,用户的身份合法方可访问该系统的资源,常见的用户身份认证的方式有:
会话:
用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保存在会话中。会话就是系统为了保持当前用户的登录状态所提供的机制。直白讲就是别每干一件事就查身份,给你个五年有效期的身份证,你带身上或者我帮你存着,有这个证明,在这期间你就不用再反复认证
常见的实现方式有基于session方式和基于token方式等
授权:
即认证通过后,也不是所有的资源都能访问。拥有资源的访问权限则正常访问,没有权限则拒绝访问
RBAC(Role-Based Access Control) 基于角色的访问控制
有很多权限,把权限一个一个加给用户很繁琐,所以 将一组权限打包给一个角色,再让用户和角色挂钩。说白了,一个角色就是一组权限。
一个用户可以拥有多个角色,一个角色可以被多个用户拥有。一个权限可以对应多个角色,一个角色可以对应多个权限。均为多对多,即RBAC底层最少需要5张表。
用户角色表(中间表,用户和角色的关系表)
角色权限表(中间表,角色和权限的关系表)
Spring Security是一个能够为基于Spring的企业应用系统提供
声明式(注解)
的安全访问控制解决方案的安全框架。
https://spring.io/projects/spring-security
给需要保护的微服务添加spring-boot-starter-security依赖即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
此时再访问上面controller中的接口,就会被Spring Security拦截,且Spring Security还提供了一个登录界面。
使用默认用户user登录,密码在控制台可找到,是一个随机生成的UUID字符串:
使用curl访问:
curl -v -X GET -u"user:550e8400-e29b-41d4-a716-446655440000" http://localhost:9527/admin/query
loclhost:port/logout
以上只是个入门案例,当然密码和用户肯定不是这么存的。
添加配置:
spring:
security:
user:
name: admin
password: admin123
重启服务,此时控制台上不再为我们生成密码,用上面自己配置的密码登录即可:
当然这个还是临时给自己调试用的,生产环境不这么搞。接下来 看下源码实现,在application.yml 中 将鼠标指定到name那,按住ctrl键,单击鼠标左键
在config目录下创建配置类:
@Configuration
public class MySecurityUserConfig {
@Bean
public UserDetailsService userDetailService() {
//使用org.springframework.security.core.userdetails.User类来定义用户
//定义两个用户
UserDetails user1 = User.builder().username("liu").password("123456").roles("student").build();
UserDetails user2 = User.builder().username("Mr.liu").password("123456").roles("teacher").build();
//创建两个用户,信息存内存中
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
userDetailsManager.createUser(user1);
userDetailsManager.createUser(user2);
return userDetailsManager;
}
}
重启服务,访问接口,跳登录页面后,输入上面定义的用户名和密码,控制台报错:
这个是因为spring Sercurity强制要使用密码加密,当然我们也可以不加密,但是官方要求是不管你是否加密,
都必须配置一个密码编码(加密)器
继续在MySecurityUserConfig类中定义bean:
/*
* 从 Spring5 开始,强制要求密码要加密
* 如果非不想加密,可以使用一个过期的 PasswordEncoder 的实例 NoOpPasswordEncoder,
* 但是不建议这么做,毕竟不安全。
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
//不对密码进行加密,使用明文
return NoOpPasswordEncoder.getInstance();
}
重启后再登录上面定义的用户,则可以登录成功。且此时,yaml配置文件中的用户名和密码就失效了。此时,有以下几个问题: