目录
概念
JPA的具体实现
1、引入依赖
2、domain模块配置yml文件
3、实体类(以权限表为例)
4、user模块配置yml文件
5、Dao层接口
6、Service层接口及实现类(以UserService为例)
7、Controller控制层
8、单元测试
9、启动类添加@EntityScan引入实体类的包
概念
基于角色的访问控制(Role-Based Access Control),它包括用户 / 角色 / 权限。
1、用户是发起操作的主体, 按类型分可分为 2B 和 2C 用户, 可以是后台管理系统的用户, 可以是 OA 系统的内部员工, 也可以是面向 C 端的用户, 比如阿里云的用户。
2、角色起到了桥梁的作用, 连接了用户和权限的关系, 每个角色可以关联多个权限, 同时一个用户关联多个角色, 那么这个用户就有了多个角色的多个权限。
一个角色可以与多个用户关联, 管理员只需要把该角色赋予用户, 那么用户就有了该角色下的所有权限, 这样设计既提升了效率, 也有很大的拓展性。
3、权限:
是用户可以访问的资源, 包括页面权限, 操作权限, 数据权限:
- 页面权限:
即用户登录系统可以看到的页面, 由菜单来控制, 菜单包括一级菜单和二级菜单, 只要用户有一级和二级菜单的权限, 那么用户就可以访问页面 - 操作权限:
即页面的功能按钮,包括查看, 新增, 修改, 删除, 审核等,用户点击删除按钮时,后台会校验用户角色下的所有权限是否包含该删除权限。如果是, 就可以进行下一步操作, 反之提示无权限。
有的系统要求 "可见即可操作", 意思是如果页面上能够看到操作按钮, 那么用户就可以操作, 要实现此需求, 这里就需要前端来配合, 前端开发把用户的权限信息缓存, 在页面判断用户是否包含此权限, 如果有, 就显示该按钮, 如果没有, 就隐藏该按钮。在实际场景可自行选择是否需要这样做,有利于提升用户体验。
- 数据权限:
数据权限就是用户在同一页面看到的数据是不同的,比如财务部只能看到其部门下的用户数据,人事部只看人事部的数据。
JPA的具体实现
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2、domain模块配置yml文件
3、实体类(以权限表为例)
@Table(name = "privs_tab")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Privs {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="privs_id")
private Long id;
@Column(name="privs_name")
private String name;
@Column(name="privs_desc")
private String desc;
@Column(name="privs_create_by")
private String createBy;
@Column(name="privs_create_time")
private Date createTime;
@Column(name="privs_update_time")
private Date updateTime;
}
4、user模块配置yml文件
server:
port: 9099
spring:
application:
name: bms-user
#屏蔽mybatisplus的多数据源自动启动
autoconfigure:
exclude: com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration
logging:
level:
com.wnhz.bms.user: debug
5、Dao层接口
@Repository
public interface PrivsDao extends JpaRepository<Privs,Long> {
}
@Repository
public interface UserDao extends JpaRepository<User,Long> {
//根据user的username和password查询该用户的权限privs
User findByUsernameAndPassword(String username,String password);
}
@Repository
public interface RoleDao extends JpaRepository<Role,Long> {
}
@Repository
public interface RolePrivsDao extends JpaRepository<RolePrivs,Long> {
@Query(value = "SELECT * FROM rp_tab WHERE rp_role_id=?",nativeQuery = true)
List<RolePrivs> findRpsByRoleId(Long roleId);
}
6、Service层接口及实现类(以UserService为例)
public interface UserService {
//根据user的username和password查询该用户的权限privs
List<Privs> findUserPrivs(String username, String password);
//全查询
List<User> findAllUsers();
//删除
void deleteUser(Long id);
//使用jpa查询某个用户的角色名称及权限
UserVo findUserRoleNameAndPrivs(String username, String password);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
@Autowired
private RolePrivsDao rolePrivsDao;
@Autowired
private PrivsDao privsDao;
//根据user的username和password查询该用户的权限privs
@Override
public List<Privs> findUserPrivs(String username, String password) {
List<Privs> privsList = new ArrayList<>();
User user = userDao.findByUsernameAndPassword(username, password);
Long roleId = user.getRoleId();
List<RolePrivs> rpsByRoleId = rolePrivsDao.findRpsByRoleId(roleId);
rpsByRoleId.forEach(rolePrivs -> {
Long privsId = rolePrivs.getPrivsId();
privsList.add(privsDao.findById(privsId).get());
});
return privsList;
}
//全查询
//@Cacheable(cacheNames = "findAllUsers") //第一次查询完就放入缓存
@CachePut(cacheNames = "findAllUsers") //每次查询每次进缓存
@Override
public List<User> findAllUsers() {
return userDao.findAll();
}
//删除
@CacheEvict(cacheNames = "findAllUsers",key = "#id")
@Override
public void deleteUser(Long id) {
userDao.deleteById(id);
}
//使用jpa查询某个用户的角色名称role及权限privs
@Override
public UserVo findUserRoleNameAndPrivs(String username, String password) {
List<Privs> privsList = new ArrayList<>(); //创建一个空的权限列表 privsList,用于存储查询到的权限信息
User user = userDao.findByUsernameAndPassword(username, password); //根据用户名和密码查询用户信息,
Long roleId = user.getRoleId(); //并获取用户的角色ID。
List<RolePrivs> rpsByRoleId = rolePrivsDao.findRpsByRoleId(roleId); //根据角色ID查询角色权限关系列表
rpsByRoleId.forEach(rolePrivs -> { //遍历角色权限关系列表
Long privsId = rolePrivs.getPrivsId(); //获取权限ID
privsList.add(privsDao.findById(privsId).get()); //根据权限ID查询对应的权限对象,并添加到权限列表privsList中
});
Role role = roleDao.findById(roleId).get(); //根据角色ID查询角色对象
UserVo userVo = new UserVo(); //创建一个 UserVo 对象
//将查询到的用户信息、角色信息和权限列表信息分别设置到 UserVo 对象中的相应属性
userVo.setUser(user);
userVo.setRole(role);
userVo.setPrivs(privsList);
//返回封装好的 UserVo 对象
return userVo;
}
}
7、Controller控制层
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/findAllUsers")
public HttpResp<List<User>> findAllUsers(){
return HttpResp.success(userService.findAllUsers());
}
@DeleteMapping("rmUser")
public HttpResp rmUser(Long id){
userService.deleteUser(id);
return HttpResp.success("删除用户"+id+"成功");
}
}
8、单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceImplTest {
@Autowired
private UserService userService;
@Test
public void findUserPrivs() {
List<Privs> list = userService.findUserPrivs("jpa", "123");
list.forEach(e-> System.out.println(e.getName()));
}
//使用jpa查询某个用户的角色名称及权限
@Test
public void findUserRoleNameAndPrivs() {
UserVo jpa = userService.findUserRoleNameAndPrivs("jpa", "123");
System.out.println(jpa.getRole().getName()+"-"+jpa.getPrivs().toString());
}
}
9、启动类添加@EntityScan引入实体类的包
@SpringBootApplication
@EntityScan(basePackages = "com.****.bms.domain.entity.jpa")
@EnableCaching //开启spring缓存
public class UserApp {
public static void main(String[] args) {
SpringApplication.run(UserApp.class);
}
}