数据拉取与推送之jwt+shiro+模板模式实现推送(二)

3 篇文章 0 订阅
2 篇文章 0 订阅

目录

前言

数据接口推送是开发中最常见的问题。也有很多实现手段,比如基于webservice,如果实时性要求很高的也可以使用MQ等。当然也可以使用传统的基于http请求的。而这里采用基于http请求的,数据返回格式统一采用restful形式

整体设计

为了承接job功能利用httpClient拉取接口,这里简化需求,模型和其他干扰因素。即按照分页的模式读取表中的符合的数据并实现接口暴露给外部,同时每一次拉取数据都要校验其合法性。不妨先鸟瞅整体一下,如图所示

整体架构时序图

表设计

类OAuth2的用户名密码模式,我们需要一个用户认证的信息记录表,如果合法,每个用户获取其有效的access_token

api_user(用户表)

CREATE TABLE `api_user`  (
  `user_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户id',
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `pass_word` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
  `salt` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '盐值',
  `status` int(4) NULL DEFAULT NULL,
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

除此之外,我们还需要对每个用户的token信息进行记录,并且约定每个用户只会有一个token记录,token只会对当日有效

api_user_token(用户token记录表)

CREATE TABLE `test`.`api_user_token`  (
  `user_id` varchar(36) NOT NULL COMMENT '用户id',
  `start_time` datetime(0) NULL COMMENT '授权开始时间',
  `end_time` datetime(0) NULL COMMENT '授权结束时间',
  `auth_time` datetime(0) NULL COMMENT '授权时间',
  `access_token` varchar(255) NULL COMMENT 'Token令牌',
  `token_create_time` datetime(0) NULL COMMENT 'Token生成时间',
  `token_end_time` datetime(0) NULL COMMENT 'Token失效时间',
  `token_count` int(10) NULL COMMENT '当日token生成次数',
  `last_update_time` datetime(0) NULL COMMENT '最后更新时间',
  `last_update_user` varchar(255) NULL COMMENT '最后更新人',
  PRIMARY KEY (`user_id`)
) COMMENT = '用户token记录表';

事实上该记录远不止这些,这里仅仅做了简化,其中start_time与end_time控制用户访问接口的整个有效期,token_end_time用来控制token的有效期,其他作为记录。
但是这里仅仅只要求token当日有效,并且每次访问只能是携带该表中最新token才放行访问推送接口(token接口不做限制)

权限设计

上面是系统权限表设计,主要还是采用OAuth2用户名密码模式思想。当然随之而来的就是用户业务权限,也就是用户会有哪些接口的权限,这里简化,即接口服务表api_auth与映射表api_user_auth,最后控制用户可以访问哪些接口

api_auth(接口服务表)

CREATE TABLE `test`.`api_auth`  (
  `service_id` varchar(36) NOT NULL COMMENT '服务ID',
  `service_name` varchar(255) NULL COMMENT '服务名称',
  `service_remark` varchar(255) NULL COMMENT '服务说明',
  `service_url` varchar(255) NULL COMMENT '服务相对路径',
  `status` int(4) NULL COMMENT '服务状态',
  PRIMARY KEY (`service_id`)
) COMMENT = '接口服务表';

该表作为接口服务基础表,其中service_url是作为服务请求是否正确的依据

api_user_auth(用户接口权限表)

CREATE TABLE `test`.`Untitled`  (
  `user_id` varchar(36) NOT NULL COMMENT '用户id',
  `service_id` varchar(255) NULL COMMENT '服务ID',
  PRIMARY KEY (`user_id`)
) COMMENT = 'api_user_auth';

很显然通过基础接口服务与映射表可以很好的控制业务权限

模式设计

基本权限思路已经完成,很显然就是如何设计使代码的可读性,可扩展性与可维护性都很好了。
很显然我们这里可以抽象为校验与数据处理,而校验的行为都一样,只是不同业务的行为(如不同接口读取数据不一样),所以模板设计模式就可以解决。不过还是推荐使用工厂方法模式+策略模式去扩展,因为可能针对不同的大的分类业务会有不同的策略去处理
话不多说,如下图所示

模板模式

码上有戏

如图,为项目代码结构
项目代码结构

核心代码

由于http是无状态的请求,所以每次请求需要权限控制,通过shiro控制权限,除了gettoken放行外,其余请求都JwtFilter去拦截,判断token是否合法

ShiroConfig

   @Bean("shiroFilter")
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        Map<String, Filter> filters = new HashMap<>();
        filters.put("oauth2", new JwtFilter());
        shiroFilter.setFilters(filters);

        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/api/study/gettoken", "anon");
        filterMap.put("/**", "oauth2");
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

JwtRealm进行授权和身份认证

 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        JwtToken jwtToken = (JwtToken) token;
        if (jwtToken == null) {
            throw new AuthenticationException("token不能为空");
        }


        String accessToken = (String) token.getPrincipal();
        ApiUserToken userToken = apiUserTokenService.getOne(new QueryWrapper<ApiUserToken>().eq("access_token", accessToken));

        //判断token是否失效
        boolean flag = userToken == null || userToken.getTokenEndTime().getTime() < System.currentTimeMillis();

        if (flag) {
            throw new IncorrectCredentialsException("token失效");
        }
        ApiUser user = apiUserService.getById(userToken.getUserId());

        if (user.getStatus() == 0) {
            throw new LockedAccountException("账号已被禁用,请联系管理员");
        }

        String salt = user.getSalt();
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, ByteSource.Util.bytes(salt), getName());
        return info;
    }

RequestModel与ResponseModel作为最顶层接受与返回类,抽象共有参数

AbstractApiRequest为抽象一套模板,主要为校验token和权限,之后子类ApiXXRequest去实现action方法,并且转型为子类的xxRequestModel与xxResponseModel返回数据

postman测试

至此我们可以扩展推送功能,比如增加一个apiXXrequest与表,从而推送业务数据

1,获取token测试
get请求输入 http://localhost:8087/api/study/gettoken?username=admin&password=123456

在这里插入图片描述
2 获取api_leesin推送数据
http://localhost:8087/api/study/getinformation/leesinlist?token=最新token
然后需要携带分页参数:{“data”:"{“pageindex”:“1”}"}

在这里插入图片描述
3 获取api_yurnero推送数据 同二步骤
http://localhost:8087/api/study/getinformation/yurnerolist?token=最新token

源码地址

github地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值