青锋开源架构-springboot2.6.x+vue3-antdesign-vite: 青锋-springboot2.6.x+vue3-antdesign-vite开源架构,实现了系统管理模块、权限控制模块(菜单权限、功能按钮权限、数据权限)、代码生成器(单表、树表)、quartz动态定时器等功能。
Spring Security中有一些概念和实现,例如GrantedAuthority用于获得授权来授权/控制访问权限的接口。
我希望对允许的操作(例如userList或user:del)进行允许,这些操作将允许管理员(具有role ROLE_ADMIN)使用。
通过查看org.springframework.security.core.userdetails.UserDetails了身份验证提供程序引用的DAO中使用的接口,该接口消耗了User(请注意最后的GrantedAuthority):
public User(String username,
String password,
boolean enabled,
boolean accountNonExpired,
boolean credentialsNonExpired,
boolean accountNonLocked,
Collection extends GrantedAuthority> authorities)
当用户执行登录验证之后,查询对应的权限集合authorities,将权限集合返回到User对象中。
我们可以通过userDetailsService.loadUserByUsername("admin").getAuthorities()获取用户的权限信息,这里的权限信息就是上面讲解的authorities设置的权限信息。
userDetailsService.loadUserByUsername("admin").getAuthorities()
我们在SecurityConfigure中设置权限的身份认证,如下:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder);
}
我们通过查询当前登录用户的权限信息,并将权限信息返回到User中。
List grantedAuthorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(permissions);
AuthUser authUser = new AuthUser(uPd.get("login_name").toString()+":"+uPd.get("id").toString()+":"+organize_id, uPd.get("login_password").toString(), true, true, true, notLocked,
grantedAuthorityList);
AuthUser继承了User接口,我们通过查看User构造方法如下:
详细代码如下:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
PageData pd = new PageData();
if(username.contains(":")){
pd.put("login_name",username.split(":")[0]);
}else{
pd.put("login_name",username);
}
PageData uPd = userManager.findUserInfo(pd);
System.out.println(uPd);
if(Verify.verifyIsNotNull(uPd)){
System.out.println(uPd.get("status"));
if(uPd.get("status").equals("2")){
throw new UsernameNotFoundException("账号已休眠,请联系管理员");
}else{
if(uPd.get("status").equals("0")){
//查询当前用户组织
pd.put("user_id",uPd.get("id"));
PageData orgPd = userManager.findUserOrganizeInfo(pd);
String organize_id = "";
if(Verify.verifyIsNotNull(orgPd)){
organize_id = orgPd.get("organize_id")+"";
}
//登录成功
pd.put("user_id",uPd.get("id"));
String permissions = userManager.findUserPermissions(pd);
// System.out.println("===================================查询出来数据权限==============================");
// System.out.println(permissions);
boolean notLocked = false;
if (StringUtils.equals("0", uPd.get("status").toString()))
notLocked = true;
List grantedAuthorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(permissions);
AuthUser authUser = new AuthUser(uPd.get("login_name").toString()+":"+uPd.get("id").toString()+":"+organize_id, uPd.get("login_password").toString(), true, true, true, notLocked,
grantedAuthorityList);
return transToAuthUser(authUser,uPd);
}else if(uPd.getString("status").equals("1")){
throw new UsernameNotFoundException("账号已禁用,请联系管理员");
}else if(uPd.getString("status").equals("2")){
throw new UsernameNotFoundException("账号已休眠,请联系管理员");
}
}
return null;
}else{
throw new UsernameNotFoundException("登录名称不存在,请重新输入。");
}
}
通过SQL可以看到,数据权限perms的权限是通过父节点菜单的权限标识符:按钮功能权限标识符,比如用户的查看、新增、编辑、删除方法:
user:info
user:add
user:edit
user:del
请求方法中,通过增加注解:@PreAuthorize("hasAnyAuthority('xxx:xxx')")进行权限控制:
@PreAuthorize("hasAnyAuthority('xxx:xxx')")
下面以系统用户权限控制方法进行讲解:
/**
* @title listPage
* @description 查询数据分页列表
* @author Administrator
* @updateTime 2022/1/19 0019 23:41
*/
@GetMapping("/listPage")
@PreAuthorize("hasAnyAuthority('user:info')")
public MyResponse listPage(QueryRequest queryRequest, Area area) {
String userParams = SecurityContextHolder.getContext().getAuthentication().getName();
return new MyResponse().data(dataTable);
}
/**
* @title save
* @description 保存数据
* @author Administrator
* @updateTime 2022/1/19 0019 23:41
*/
@PostMapping
@PreAuthorize("hasAnyAuthority('user:add')")
public void save(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
this.writeJson(response,json);
}
/**
* @title update
* @description 更新数据
* @author Administrator
* @updateTime 2022/1/19 0019 23:41
*/
@PutMapping
@PreAuthorize("hasAnyAuthority('user:edit')")
public void update(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
Json json = new Json();
this.writeJson(response,json);
}
/**
* @title delete
* @description 删除数据
* @author Administrator
* @updateTime 2022/1/19 0019 23:41
*/
@DeleteMapping("/{ids}")
@PreAuthorize("hasAnyAuthority('user:del')")
public void delete(@NotBlank(message = "{required}") @PathVariable String ids,HttpServletResponse response) throws Exception {
Json json = new Json();
this.writeJson(response,json);
}
/**
* @title updateStatus
* @description 更新状态
* @author Administrator
* @updateTime 2022/1/19 0019 23:41
*/
@PostMapping("/updateStatus")
@PreAuthorize("hasAnyAuthority('user:status')")
public void updateStatus(@Valid @RequestBody Area area,HttpServletResponse response) throws Exception {
Json json = new Json();
this.writeJson(response,json);
}
看到这里,大家可能会有疑问,上面提到的user:add,用户菜单user和添加按钮add在哪里设置的呢?