nacos源码之Auth(权限)模块-1(授权过滤器与控制器缓存)
发布日期:2021-06-30 16:13:13 浏览次数:2 分类:技术文章

本文共 4307 字,大约阅读时间需要 14 分钟。

下一篇:


Nacos的Auth模块



上一篇《nacos源码构建与总览》浏览器还挺多,接下来模块的精讲来了

Nacos的Auth模块

auth模块管理了nacos的权限,该权限系统设计面向租户模式,功能比较简单,不适用于业务系统。

授权过滤器(权限核心注解)

源码如下:

package com.alibaba.nacos.auth.annotation;@Retention(RetentionPolicy.RUNTIME)public @interface Secured {
// 操作类型(nacos只定义了读和写两种操作类型) ActionTypes action() default ActionTypes.READ; // 操作的资源 String resource() default StringUtils.EMPTY; Class
parser() default DefaultResourceParser.class;}

nacos 权限模块只定义了两种操作类型,。但从这个角度也无法胜任业务系统的权限框架,但是对于服务发现,配置管理视乎也够用了。

在一个通用的权限框架中,权限框架只需要管理权限资源的操作类型是否通过即可,这一点Nacos是相同的。

注解实现讲解

这里就是整个权限模块的核心了。

该注解的实现并不在auth包下,但是注解的实现也是属于权限模块的,因此在本章节讲解。

看这个代码之前,先强调一些知识,帮助理解nacos的权限实现 :

  1. nacos使用spring mvc架构。因此它是servlet,并不是netty的非阻塞框架。
  2. nacos注解使用过滤器实现。

nettyservlet并没有优略之分,它们两个亦不是水火不容,使用netty还是使用servlet,需要根据解决问题的场景参考,它们本身就是为服务实现提出的不同的解决方案。

由于代码篇幅过长,带有备注的代码已经提交到 ,请见 :

核心片段:

// 获取缓存方法            Method method = methodsCache.getMethod(req);            // 没有匹配到方法,说明未被权限模块扫描,直接放行            if (method == null) {
chain.doFilter(request, response); return; } // 如果含有权限注解才去进行权限校验 if (method.isAnnotationPresent(Secured.class) && authConfigs.isAuthEnabled()) {
Secured secured = method.getAnnotation(Secured.class); String action = secured.action().toString(); String resource = secured.resource(); if (StringUtils.isBlank(resource)) {
ResourceParser parser = getResourceParser(secured.parser()); resource = parser.parseName(req); } if (StringUtils.isBlank(resource)) {
// 如果没有匹配到资源直接报权限异常 throw new AccessException("resource name invalid!"); } // 进行授权校验,不通过就抛出AccessException authManager.auth(new Permission(resource, action), authManager.login(req)); }

注解的核心实现在集成的doFilter方法中实现,随便吐槽一下,这里面的代码似乎并不是特别优雅。

小知识来了 :

授权过滤器中使用了ConcurrentHashMap,这个集合并发度是比较牛的。这里不讲多线程,粗略的说一下原理,HashTable使用的是 synchronized关键字,是对整个对象加锁,而 ConcurrentHashMap采用了分段锁。有兴趣的可以评论区留言

实现逻辑:

  1. 首先判断是否开启权限控制。这个功能在权限配置中实现,具体见下面的权限配置
  2. 然后判断了是否开启白名单。处理方式也很简单,直接交给其他过滤器解决。但是还是加了些判断,判断请求头里是否含有User-Agent属性,有的话才去交给另一个过滤器执行。
  3. 第三个判断就判断了是否含有授权Key,如果请求头里面含有授权Key,就和配置的授权信息比较,如果相同就交给其他过滤器执行。
  4. 如果啥都没有,就会执行到403。好歹你得给点东西证明一下你是谁吧。要不然不能过。
  5. 接下来就是权限控制了。先去请求缓存中获取请求,判断一下方法上是否含有权限注解(Secured),如果没有权限注解自然是直接放行。
  6. 如果使用了权限注解,获取操作类型,和资源类型,然后比较权限,符合就服务,不符合就抛异常,具体实现在AuthManager(授权管理)中实现。
  7. 如果AuthManager(授权管理) 权限校验没有通过就抛出AccessException
  8. 如果捕捉到AccessException,请求结束返回 403


权限操作类型

如上所述:nacos只有读和写两种操作类型,定义如下 :

package com.alibaba.nacos.auth.common;public enum ActionTypes {
/** * Read. */ READ("r"), /** * Write. */ WRITE("w"); private String action;}

控制器缓存

控制器缓存用来解决多次反射的问题,在Nacos启动时扫描所有控制器,将请求路径与控制器方法匹配。

内部实现了两个Map,map使用 ConcurrentHashMap 实现,保证了高并发的效率,有了该缓存也减少了反射的次数,提供了Nacos的性能。

内部两个Map定义如下:

// 请求与方法的对照表    private ConcurrentMap
methods = new ConcurrentHashMap<>(); // 请求地址与请求方法的匹配集合 private final ConcurrentMap
> urlLookup = new ConcurrentHashMap<>();
  1. methods是请求与方法的对应表,一个请求对应一个方法。
  2. urlLookup是地址与请求列表的对应表,key是地址,格式为POST-->com.alibaba.nacos.core.controller/nacos/v1/install,正常情况下一个地址对应一个请求,但是可能存在一个请求地址对应多个请求

获取方法

在权限过滤器中,在执行注解逻辑中,首先需要根据请求,从缓存控制器中找到匹配的方法。

Method method = methodsCache.getMethod(req);

获取方法实现逻辑如下:

  1. 获取请求路径,组装出urlLookup关系表中的Key。
  2. 根据拼接出来的请求路径获取到匹配的请求列表。
  3. 匹配列表筛选出最佳匹配的请求对象RequestMappingInfo
  4. 根据请求对象找到对应的Method,并且返回。

初始化两个对象表

初始化方法:

/**     * init初始化反射方法     *     * @param packageName package name     */    public void initClassMethod(String packageName) {
Reflections reflections = new Reflections(packageName); Set
> classesList = reflections.getTypesAnnotatedWith(RequestMapping.class); for (Class clazz : classesList) {
initClassMethod(clazz); } }

反射Nacos使用了 reflections技术,Maven依赖如下:

org.reflections
reflections
0.9.12

代码篇幅过长,已提交至Github,完整代码请见 (已经添加了注解):

Naco读后感

使用对象缓存,减少了反射次数,反射比较耗费性能,这样做大大提高了性能,这种方式效率是高于Sping AOP的,因为并不是每次都需要做反射。

ConcurrentHashMap保证了多线程的效率。分段锁要比对象锁效率要高。

使用别人造好的轮子reflections,减少了反射的代码量和使用难度。

SRP(单一职责原则),单一职责原则不但可以降低复杂度,帮助编程人员理清逻辑,还可以很大程度提高代码可读性,既见既所得。


下一篇:

转载地址:https://keepgoon.blog.csdn.net/article/details/116752891 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:nacos源码之Auth(权限)模块-2(权限管理与权限配置)
下一篇:一文道尽分布式的CAP原则

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年05月04日 10时47分13秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章