项目是基于jhipster生成的后端项目,使用spring boot相关的技术。
我的做法:
在JWT的FILTER里面,添加自己的一些业务逻辑,把数据和菜单权限信息获取到, 并存到JWT中去。
String login = "admin"; String DATA_ACL_STR = ""; try { login = claims.get("sub").toString(); DATA_ACL_STR = resAclRepository.findAclByUser(login); } catch (Exception ex) { ex.printStackTrace(); } Collection<? extends GrantedAuthority> authorities = Arrays .stream((claims.get(AUTHORITIES_KEY).toString() + "," + DATA_ACL_STR).split(",")) .map(SimpleGrantedAuthority::new).collect(Collectors.toList()); User principal = new User(claims.getSubject(), "", authorities); SecurityContextHolder.getContext().setAuthentication(principal);
用到的两张表的设计如下:
CREATE TABLE `t_res_acl` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `jhi_role` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `res_type` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `res_value` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `created_time` datetime DEFAULT NULL, `created_by` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, `modified_time` datetime DEFAULT NULL, `modified_by` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE `t_menu_res` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `menu_type` varchar(255) NOT NULL, `pid` bigint(20) DEFAULT NULL, `permission` varchar(255) NOT NULL, `jhi_disable` bit(1) DEFAULT NULL, `created_time` datetime, `created_by` varchar(255) DEFAULT NULL, `modified_time` datetime, `modified_by` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
使用一个自定义的AOP拦截器,拦截特定的几个方法,这几个特定的方法都有一个业务字段,暂且仅对业务进行数据控制。
拦截到的方法从
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
从这个getAuthorities中进行数据检查,因为在前面的JWT FILTER中把权限信息存在这里了。
同时,在JWTFILTER里根据获取到的用户请求的URL和请求的方法,可以判断是否是需要保护的资源,如果是,则同样从权限中确认一下,
如果没有访问权限,则中止过滤器,否则继续。
// 判断权限中是否含有当前URL的访问权限
if (!authentication.getAuthorities().contains(new SimpleGrantedAuthority(AuthoritiesConstants.ADMIN)) // 管理员角色用户不判断权限 && this.tokenProvider.ValidateMenuRes(permission) // 此资源是需要保护的 && !authentication.getAuthorities().contains(new SimpleGrantedAuthority(permission))) { servletResponse.getWriter().write("Current User is not authorized to access resource:" + permission); return; }