让老项目加入你的NACOS微服务框架,并集成权限

编程入门 行业动态 更新时间:2024-10-19 15:23:40

让老项目加入你的NACOS微服务<a href=https://www.elefans.com/category/jswz/34/1770644.html style=框架,并集成权限"/>

让老项目加入你的NACOS微服务框架,并集成权限

前言

        为了让老项目加入新的云服务中,可能要进行一些改造,老项目无需加入Security就可以简单的使用权限系统

准备工作

        首先要拥有一个完整的基于NACOS的微服务框架和一个Springboot老项目

        微服务框架使用了Security,并支持Auth2.0 

        老框架没有任何权限系统,或权限系统已经不起作用

接口权限验证接口

        这里定义一个接口专门用来判断当前登录用户的token是否包含某个权限编码

        这里一般将功能集成到微服务框架的Auth模块中

        

public interface TokenService {/*** 通过token获取权限列表* @param token* @return*/Collection<GrantedAuthority> getPermissionByToken(String token);
}
@Service
public class TokenServiceImpl implements TokenService {@Autowiredprivate TokenStore tokenStore;@Overridepublic Collection<GrantedAuthority> getPermissionByToken(String token) {if (StringUtils.isEmpty(token)) {return new ArrayList<>();}OAuth2Authentication auth =  tokenStore.readAuthentication(token);if(!auth.isAuthenticated()){return new ArrayList<>();}return auth.getAuthorities();}
}
    /*** 判断指定token是否包含某个权限值* @param token* @return*/@GetMapping("/hasPermissions")public AjaxResult getPermissionByToken(@RequestParam("token") String token,@RequestParam("permission") String permission){Collection<GrantedAuthority> authorities = tokenService.getPermissionByToken(token);if(null==authorities||authorities.isEmpty()){return AjaxResult.success(false);}Boolean result = permissionService.hasPermi(authorities,permission);System.out.println(result?"有权限":"无权限");return AjaxResult.success(result);}

 这里是hasPermi方法,不多做解释

    /*** 验证用户是否具备某权限** @param permission 权限字符串* @return 用户是否具备某权限*/public boolean hasPermi(Collection<GrantedAuthority> authorities, String permission){if (StringUtils.isEmpty(permission)){return false;}if (null==authorities||authorities.isEmpty()){return false;}return hasPermissions(authorities, permission);}
    /*** 判断是否包含权限* * @param authorities 权限列表* @param permission 权限字符串* @return 用户是否具备某权限*/private boolean hasPermissions(Collection<? extends GrantedAuthority> authorities, String permission){return authorities.stream().map(GrantedAuthority::getAuthority).filter(StringUtils::hasText).anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x));}

 

我们可以通过以下URL判断该接口是否可用,当然,这个接口的访问权限是everyone或All

localhost:8080/auth/token/hasPermissions?token=4657eaca-5458-4a55-aa38-a63c02173611&permission=sysuser:edit

老项采用注解方式

        首先老项目最好加入到Nacos发现服务中,这个只要通过配置就可以实现

        当然你也可以让你的老项目单独运行

        在老项目中写一个注解,这里使用shiro的命名方式 RequiresPermissions 当然 你也可以使用其他的命名,比如hasPer等等,这里的例子支持一个权限,你也可以让他支持OR或者AND等逻辑就更完美了

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissions {String[] value();//实在是不想写这些逻辑了
//    Logical logical() default Logical.AND;}

接下来就是切面逻辑了,通过代码 我们可以看出,该切面先到getParamter中获取token如果没有就到header中获取token,最后通过token到微服务框架中判断权限是否存在,这里使用restTemplat,你也可是使用你喜欢的方式比如openFeign甚至HttpClient

/*** 权限判断,切面处理类*/
@Slf4j
@Aspect
@Component
public class RequiresPermissionsAspect {@AutowiredRestTemplate restTemplate;@Pointcut("@annotation(com.fangshengmon.auth.annotation.RequiresPermissions)")public void logPointCut() {}@Around("logPointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//获取请求和响应HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();//获取tokenString token = request.getParameter("token");if(StringUtils.isEmpty(token)){token = request.getHeader("token");if(StringUtils.isEmpty(token)){log.error("[UNAUTHORIZED] not auth ");WebUtils.printErrorPage(401,"无权限:1",response);return null;}}//获取标签信息MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();RequiresPermissions permissions = method.getAnnotation(RequiresPermissions.class);Map<String, Object> mapNode = new HashMap<>(2);mapNode.put("token", token);mapNode.put("permission",permissions);//这里使用restTemplate访问微服务Auth模块我们自己定义的接口HashMap result = restTemplate.getForObject("http://fangsheng-auth/token/hasPermissions?token={token}&permission={permission}", HashMap.class, mapNode);if (200 != (int) result.get("code")) {log.error("[UNAUTHORIZED] not auth ");WebUtils.printErrorPage(401,"无权限:2",response);return null;}if((boolean)result.get("data")){return joinPoint.proceed();}WebUtils.printErrorPage(401,"无权限:3",response);return null;}
}

这里用到一个 printErrorPage方法 贴出来方便大家复制

/*** 输出错误页* @param code* @param msg* @param resp*/public static void printErrorPage(int code, String msg, HttpServletResponse resp) {try{resp.setHeader("content-type", "text/html;charset=utf-8");resp.setCharacterEncoding("UTF-8");resp.setStatus(code);PrintWriter out = resp.getWriter();out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");out.write("<h1>服务器发生错误 code:"+ code +"</h1>");out.write("<script>alert('"+msg+"')</script>");out.write("<p>"+msg+"</p>");out.flush();out.close();}catch (Exception e){resp.setStatus(500);}}

最后将这个注解使用到接口方法上即可

    @RequiresPermissions("process:processSet:list")

在Acitivi5流程引擎中 传递使用token

        这部分内容在老系统使用activiti5工作流时使用

        首先要找到 ModelSaveRestResource.java 将注解用在saveModel方法上

    @RequiresPermissions("process:processSet:list")@RequestMapping(value = "/model/{modelId}/save/{typeId}", method = RequestMethod.PUT)@ResponseStatus(value = HttpStatus.OK)public R saveModel(@PathVariable String modelId, @PathVariable String typeId

        这时会发现无论有没有权限,都无法保存,因为token并没有传递过来

        这时候我们需要找到相应html页面将token传递

        首先找到 toolbar-default-actions.js 文件中的 $scope.save = function (successCallback) 方法、行数在330行左右

        在这个方法的上面,增加如下方法

        

$scope.getQueryVariable=function(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);};

        然后在save方法中增加如下代码,其中包含token 这个typeId如果业务需求不需要可以不用

var typeId = $scope.getQueryVariable("typeId")
var token = $scope.getQueryVariable("token")

        最后修改该方法中的ajax请求 修改如下 (主要是header放了一个token其他不变

            // Update$http({method: 'PUT',data: params,ignoreErrors: true,headers: {"token":token,'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},transformRequest: function (obj) {var str = [];for (var p in obj) {str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));}return str.join("&");},url: KISBPM.URL.putModel(modelMetaData.modelId, typeId)

到这里基本OK了,其他的就是看如何将token传递到这个editor的页面中

在这里举了一个新建流程的传入token的例子

这里注意到使用了我们自己创建的注解,并且把token传递到了对应的modeler.html页面中

/*** 新建一个空模型** @return* @throws UnsupportedEncodingException*/@RequiresPermissions("process:processSet:list")@GetMapping("newModel")public Object newModel(String typeId, @RequestParam("token") String token) throws UnsupportedEncodingException {System.out.println(token);// 初始化一个空模型Model model = repositoryService.newModel();// 设置一些默认信息String name = "new-process";String description = "";int revision = 1;String key = "process";ObjectNode modelNode = objectMapper.createObjectNode();modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);model.setName(name);model.setKey(key);model.setMetaInfo(modelNode.toString());repositoryService.saveModel(model);String id = model.getId();// 完善ModelEditorSourceObjectNode editorNode = objectMapper.createObjectNode();editorNode.put("id", "canvas");editorNode.put("resourceId", "canvas");ObjectNode stencilSetNode = objectMapper.createObjectNode();stencilSetNode.put("namespace", ".0#");editorNode.replace("stencilset", stencilSetNode);repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));return "redirect:/modeler.html?modelId=" + id + "&token="+ token +"&typeId=" + typeId;}

测试时使用这样的URL

http://localhost/dev-api/activiti/models/newModel?typeId=1506534943352815616&token=4657eaca-5458-4a55-aa38-a63c02173611

 

此次分享已经结束,希望能够帮助到大家,感兴趣的小伙伴请点个赞支持下,谢谢

更多推荐

让老项目加入你的NACOS微服务框架,并集成权限

本文发布于:2024-03-07 09:59:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1717514.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:框架   权限   项目   NACOS

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!