Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前后端分离下的用户认证和鉴权实践(二) 权限粒度的设计 #2

Open
ZhuXS opened this issue Oct 16, 2017 · 0 comments

Comments

@ZhuXS
Copy link
Owner

ZhuXS commented Oct 16, 2017

我们为什么要区分用户权限的粒度

在不同的应用场景中,我们需要要对用户进行不同粒度的权限控制,如

  • 我们要区分对不同种类资源的权限。对于User和Job这两种不同资源的操作显然需要不同的权限
  • 我们要区分对同一种类不同实体资源的权限。对于Project1和Project2这两个不同的实体,需要加以不同的权限控制
  • 我们要区分对同一种类同一实体不同操作(读、删、改、创)的权限。对于Project这一种资源类型,创建操作(Post)和读操作(Read)需要不同的权限;对于同一个实体,更新操作(Put)和读操作(Read)也需要不同的权限

批量控制权限

我们需要对于权限进行批量的操作。想象这样一种应用场景,你是QQ的不锈钢贵族,你拥有10个不同的权限,同样的不锈钢贵族还有很多。难道QQ对每一个不锈钢贵族的用户都要维护其与10个权限的关联关系么,显然不是这样。这样会造成一定的数据冗余,因为每一个不锈钢贵族与权限的关联关系都是相同的,没有必要维护多次,冗余度会随着不锈钢贵族对应的权限数量的增长而变得更加严重;除此之外,还会对用户的授权和撤权造成一定的麻烦。

因此我们需要引入Role(角色)的概念,Role与Permission建立关联,User再与Role建立关联。

权限粒度设计

综上,有关权限管理,共需要三种Entity

  • User
  • Role
  • Permission
    image

User 和 Role、Permission均是多对多的关系

  • User可以拥有多种 Role,一个Role也可以赋给多个用户
  • User可以拥有多种Permission,一个Permission可以赋给多个用户

Role 和 Permission之间是多对多的关系

  • Role可以拥有多个Permission,一个Permission也可以赋给多种Role

Permission 的设计

image

  • type:资源的类型
  • id:特定资源的实体id
  • action:操作类型(GET,DELETE,PUT,POST)
  • resource:type:id,如Project:1
  • name:resource:action,如Project:1:GET,表示对id为1的Project的读权限;Job:Post,表示创建Job 的权限。

实现

使用Hibernate建立实体和实体之间的关联关系

注意三者之间的多对多的关联关系

  • User.java
    @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable(name = "user_role",
            joinColumns = {@JoinColumn(name = "userId",referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "roleId",referencedColumnName = "id")})
    private List<Role> roles = new ArrayList<>();

    @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable(name = "user_permission",
            joinColumns = {@JoinColumn(name = "userId",referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "permissionId",referencedColumnName = "id")})
    private List<Permission> permissions = new ArrayList<>(); 
  • Role.java
    @ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
    private List<User> users = new ArrayList<>();

    @ManyToMany(cascade = CascadeType.MERGE,fetch = FetchType.LAZY)
    @JoinTable(name = "role_permission",
            joinColumns = {@JoinColumn(name = "roleId",referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "permissionId",referencedColumnName = "id")})
    @CollectionId(columns = @Column(name = "id"),
            type = @Type(type = "long"),
            generator = "identity")
    private List<Permission> permissions = new ArrayList<>();
  • Permission.java
    @ManyToMany(mappedBy = "permissions",fetch = FetchType.LAZY)
    private List<Role> roles = new ArrayList<>();

    @ManyToMany(mappedBy = "permissions",fetch = FetchType.LAZY)
    private List<User> users = new ArrayList<>();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant