美文网首页
2020-02-24 abc-ares-api说明

2020-02-24 abc-ares-api说明

作者: 唯物唯心是鸡和蛋 | 来源:发表于2020-02-24 19:32 被阅读0次
    先讲一下具体流程,顺带spring的mvc分配请求处理器的逻辑。 canvas.png

    移动端app要调用api,那么我要有一个api功能,我不想用之前的非spring的api功能了,不受控制且功能不全。api模块设计如下,一个token对应一个api用户,api用户的认证和授权设计成抽象的,api模块只负责处理访问api的请求,这样api模块不依赖具体的用户管理和api权限管理;另外为了支持自定义的拦截逻辑,加入一个拦截链;另外支持注解式的权限声明(尚未写实现),和Api权限类,权限是权限,api是api,api和权限不混在一起。
    对外的接口有:ApiProvider,声明接口受我的模块管理,声明接口元信息;ApiTokenEventListener,token创建、销毁事件监听;ApiInterceptorChainNode,继承,以加入接口管理模块对接口请求的拦截处理;ApiPermission,接口权限实体;RequireApiPermissions,声明接口需要哪些权限(ApiPermission);AccessApiEvaluator,实现自定义的接口访问控制逻辑(比如,有A权限或有B权限就能访问某接口)。

    App调用api需要用户认证、设备授权校验、api权限校验、登录状态管理,就是ares模块负责的四件事。
    用户认证和设备授权认证,设计成抽象的,不依赖具体的设备管理方式和用户管理方式,交给外部实现。
    Ares要管理用户登录状态,使用SessionManager,Session包含用户信息、用户所在的设备信息、用户所在的App信息,用户登录后,利用api模块创建token,和session映射好,一旦有带token的请求过来,我能找到session,找到session,用户信息、用户设备信息、用户app信息都有了。


    image.png

    session实际就是一个抽象,代表了一次会话(一次会话就是从登录开始,到登出结束),会话就是一个抽象(非代码层面),封装了这次会话相关的信息。有了会话的概念,这样我一个token对应一个session就行了,而不用对应一堆东西,比如对应一个token,对应一个用户、一个设备、一个app、一个登录时间等等。
    只要有了session,什么设备验证啊,api权限验证啊,都可以是抽象的,想怎么实现都可以,由于有了SessionManager,可以方便获取Session,由于有了ApiInterceptorChainNode,你可以加任何的拦截、认证、校验、审计等逻辑。

    讲代码读法,仍然从最具体的入手,比如com.shinow.abc.ares.api.AresAppletApiInterceptorChainNode,
    就是拦截AresApi请求的代码,

        @Override
        protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 下面两行看不懂,没关系,往下看
            if (!HandlerMethod.class.isAssignableFrom(handler.getClass())) {
                return true;
            }
    // 下面这一行,获取HandlerMethod的BeanType的注解AresAppletApiProvider,AresAppletApiProvider总认识吧,写过,那HandlerMethod大概是啥,也能猜猜?
            AresAppletApiProvider aresAppletApiProvider = ((HandlerMethod) handler).getBeanType().getAnnotation(AresAppletApiProvider.class);
    // 看不懂,没关系,往下看
            if (aresAppletApiProvider == null) {
                return true;
            }
            Class<? extends AresApplet> appletClazz = aresAppletApiProvider.applet();
            if (appletClazz.isInterface() || Modifier.isAbstract(appletClazz.getModifiers())) {
                return true;
            }
    // session 干啥的文章上边说过了
            String token = TokenUtil.fromHttpServletRequest(request);
            AresSession session = aresSessionManager.fromToken(token);
    // 如果session是空,返回false,并且响应app让用户登录
            if (session == null) {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(
                        new ObjectMapper().writeValueAsString(
                                ApiResponseBodyBuilder.fail().category(ApiResponseBodyBuilder.ERROR).message("请登录。").build()
                        ));
                return false;
            }
    //  如果用户!canUseApplet,告诉app用户没有applet权限
            AresApplet applet = appletClazz.newInstance();
            if (!session.getUser().canUseApplet(applet.getId())) {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(
                        new ObjectMapper().writeValueAsString(
                                ApiResponseBodyBuilder.fail().category(ApiResponseBodyBuilder.ERROR).message("您没有使用" + applet.getDefaultName() + "(" + applet.getId() + ")的权限。").build()
                        ));
                Logger.getLogger(getClass().getName()).info("用户(" + session.getUser().getId() + ")没有使用此Applet(" + applet.getId() + ")的权限。");
                return false;
            }
    
            return true;
        }
    

    其他的代码还用看吗?主流程你都知道了,还看别的干啥😝。看看对外接口就够了(AresSessionLifecycleListener,AresSessionManager,AresDeviceManager,AresAppManager)。

    相关文章

      网友评论

          本文标题:2020-02-24 abc-ares-api说明

          本文链接:https://www.haomeiwen.com/subject/dbubqhtx.html