从零蛋开始集成Spring Security 5 (二)

139 阅读1分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。

承接上文...

3.2 设计数据类

完成数据库设计后, 再根据表的内容完成数据类的创建, 由于字段较多, 除了用户类之外, 我们只列举出权限相关的关键属性

权限类Permission:

@Data
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class Permission {
   
    // ...
    protected List<Api> apis;
​
}

角色类Role:

@Data
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class Role {
   
    // ...
    protected List<Permission> permissions;
​
}

用户类User:

@Data
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class User {
    
  protected String id;
  protected String username;
  protected String password;
  protected String name;
  protected List<Role> roles;
​
}

3.3 实现UserDetails

UserDetails是Spring Security中用户信息的来源, 用户账号密码校验/权限校验都要依托于此

想要实现RBAC模型的权限管理, 需要手动实现自己的UserDetails

先来看一下UserDetails的官方文档:

3-2-1 UserDetails官方文档中的全部方法.png

getUsername/getPassword方法不必多说, 重要的是 getAuthorities方法, 它提供了用户的权限信息, 并用此信息进行权限校验

源码中包含了一个实现UserDetails的User类, 可以作为参照

修改上一节中设计的用户类, 让它实现UserDetails:

@Data
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class User implements UserDetails {
​
  protected String id;
  protected String username;
  protected String password;
  protected String name;
  protected List<Role> roles;
​
  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return null;
  }
​
  @Override
  public boolean isAccountNonExpired() {
    return false;
  }
​
  @Override
  public boolean isAccountNonLocked() {
    return false;
  }
​
  @Override
  public boolean isCredentialsNonExpired() {
    return false;
  }
​
  @Override
  public boolean isEnabled() {
    return true;
  }
​
}

根据RBAC权限模型, 编写getAuthorities方法:

@Data
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class User implements UserDetails {
​
  protected String id;
  protected String username;
  protected String password;
  protected String name;
  protected List<Role> roles;
​
  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    HashSet<Permission> permissions = new HashSet<>();
    roles.forEach(role -> permissions.addAll(TreeUtil.extract(role.getPermissions())));
    HashSet<Api> apis = new HashSet<>();
    permissions.forEach(permission -> apis.addAll(permission.getApis()));
    return apis.stream().map(api -> new SimpleGrantedAuthority(api.getCode()))
      .collect(Collectors.toList());
  }
​
}