最近项目需求是想在项目中加入方法级别的权限控制,让有权限的用户访问指定方法。其实方法有很多,但是我们项目中使用的用户登录校验授权的框架是Security,所以直接使用这个安全框架中的方法权限功能。
首先你项目中要使用security这个安全框架去实现用户的登录及授权功能。用户登录完成之后,用户的数据会被保存在authentication全局上下文中。可以调用这个对象中的principal,强转为用户对象就可以直接拿到用户信息,如果用户信息保存到security中就很方便的实现方法级权限。
第一步:使用token获取用户所拥有的权限。
public LoginUser getLoginUserByToken(String token)
{
// 获取请求携带的令牌
if (StringUtils.isNotEmpty(token))
{
try
{
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get("login_user_key");
String userKey = getTokenKey(uuid);
LoginUser user = redisUtils.get(userKey, LoginUser.class);
return user;
}
catch (Exception e)
{
}
}
return null;
}
用户的信息是保存在redis中,而security中保存的是用户基本信息,所以我们使用token,解析token,拼接正确的redis的key然后获取用户信息,此时返回的user中就会有该用户的基本权限字段。
public List<GrantedAuthority> getAuthentication(String token) {
// 权限集合
List<GrantedAuthority> authorities = new ArrayList<>();
LoginUser user = tokenService.getLoginUserByToken(token);
// 添加基于Permission的权限信息
for (String permission : user.getPermissions()) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return authorities;
}
将返回的权限集合添加到authorities的集合中,再讲这个list设置给
UsernamePasswordAuthenticationToken
List<GrantedAuthority> authentication = this.getAuthentication(token);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, authentication);
配置好之后,想在哪个方法上进行权限验证,加上注解即可实现
@GetMapping("getById")
@PreAuthorize("hasAnyAuthority('trainPlan:trainCourseTestDetails:view','trainPlan:trainCourseTestDetails:edit')")
public void getById(Integer id) {
System.out.println("测试成功");
}
@PreAuthorize和hasAnyAuthority是security中自带的权限验证的注解,原理很简单,就是单纯的验证用户权限字符串中是否包含方法上的权限。
比如:这是前端需要权限校验的按钮,对接后台controller中的insert方法
<el-button v-if="hasPermission('bom:mainbom:mesBom:add')" type="primary" size="small"
icon="el-icon-plus" @click="add()">新建</el-button>
前端在工具类中需要写入一个组件,目的就是获取登录用的权限字符串,然后对比,对比成功这个按钮就显示出来了,这样前端也相当于做了一个验证,没有权限的用户连这个按钮都看不到,组件如下:
export function hasPermission(key) {
console.log(this.$store.state.userInfo);
return (this.$store.state.userInfo.permissions || '[]').indexOf(key) !== -1 || false
}
当用户点新增按钮的时候后端的security就会从authentication中拿到用户的权限集合,然后判断用户的权限集合中是否在方法注解中的权限集合中存在,存在即可访问对应方法。注解中还有很多的其他类型注解,代表的意思都不一样,可根据场景选择。你也可以自定义注解去实现,百度上的方法有很多。