RBAC模型的JPA简单实现-单表及多表查询

目录

概念

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);
    }
}

参考:

https://www.cnblogs.com/javawenjun/p/14884732.html

详细了解RBAC(Role-Based Access Control) - 知乎

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于RBAC模型的信息安全权限控制是一种常见的权限控制方式。在Python中,可以使用第三方库`django-rbac`来实现RBAC模型的权限控制。下面是一个简单的示例: 1. 安装`django-rbac`库 ```shell pip install django-rbac ``` 2. 在Django项目中配置`django-rbac` 在`settings.py`文件中添加以下配置: ```python INSTALLED_APPS = [ # ... 'rbac', ] MIDDLEWARE = [ # ... 'rbac.middleware.RbacMiddleware', ] ``` 3. 创建RBAC模型 在Django项目中创建一个名为`rbac`的应用,并在该应用中创建`models.py`文件。在该文件中定义RBAC模型: ```python from django.db import models class Role(models.Model): name = models.CharField(max_length=32, unique=True) permissions = models.ManyToManyField('Permission', blank=True) class Permission(models.Model): name = models.CharField(max_length=32, unique=True) url = models.CharField(max_length=128, unique=True) menu = models.ForeignKey('Menu', null=True, blank=True, on_delete=models.CASCADE) class Menu(models.Model): name = models.CharField(max_length=32, unique=True) icon = models.CharField(max_length=32, null=True, blank=True) url = models.CharField(max_length=128, unique=True) ``` 4. 创建RBAC视图 在Django项目中创建一个名为`rbac`的应用,并在该应用中创建`views.py`文件。在该文件中定义RBAC视图: ```python from django.shortcuts import render from django.views import View from rbac.models import Role, Permission, Menu class IndexView(View): def get(self, request): # 获取当前用户的角色 roles = request.user.roles.all() # 获取当前用户的权限 permissions = Permission.objects.filter(role__in=roles).distinct() # 获取当前用户的菜单 menus = Menu.objects.filter(permission__in=permissions).distinct() return render(request, 'index.html', {'menus': menus}) ``` 5. 创建RBAC模板 在Django项目中创建一个名为`templates`的目录,并在该目录中创建`index.html`文件。在该文件中定义RBAC模板: ```html {% for menu in menus %} <a href="{{ menu.url }}"> {% if menu.icon %} <i class="{{ menu.icon }}"></i> {% endif %} {{ menu.name }} </a> {% endfor %} ``` 以上示例演示了如何使用`django-rbac`库实现RBAC模型的权限控制。在实际应用中,可以根据具体需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值