写点什么

如何给网关设计一款专属的权限控制「责任链设计模式」(1)

  • 2021 年 11 月 11 日
  • 本文字数:3052 字

    阅读完需:约 10 分钟

1.多条件流程判断 权限控制


2.ERP 系统 流程审批 总经理、人事经理、项目经理


3.Java 过滤器的底层实现 Filter


比如:在 Java 过滤器中客户端发送请求到服务器端,过滤会经过参数过滤、session 过滤、表单过滤、隐藏过滤、检测请求头过滤


网关权限控制责任链模式


===========


在网关作为微服务程序的入口,拦截客户端所有的请求实现权限控制 ,比如先判断 Api 接口限流、黑名单、用户会话信息拦截。


Api 接口限流→黑名单拦截→用户会话信息拦截


GatewayHandler 抽象角色


/**


  • @title: GatewayHandler


*/


public abstract class GatewayHandler {


/**


  • 执行下一个 handler


*/


protected GatewayHandler nextGatewayHandler;


public void setNextGatewayHandler(GatewayHandler nextGatewayHandler) {


this.nextGatewayHandler = nextGatewayHandler;


}


//实现的 handler 处理方案 强制必须实现


public abstract void service();


protected void nextService() {


if (nextGatewayHandler != null)


// 指向下一关


nextGatewayHandler.service();


}


}


具体 Handler 实现


@Slf4j


@Component


public class CurrentLimitHandler extends GatewayHandler {


@Override


public void service() {


log.info("第一关 API 接口限流操作.....");


//指向下一关


nextService();


}


}


@Component


@Slf4j


public class BlacklistHandler extends GatewayHandler {


@Override


public void service() {


log.info("第二关 黑名单拦截.......");


//指向下一关


nextService();


}


}


@Component


@Slf4j


public class ConversationHandler extends GatewayHandler {


@Override


public void service() {


log.info("第三关 用户的会话信息拦截.......");


}


}


基于数据库实现



相关 SQL 语句


CREATE TABLE gateway_handler (


ID int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 ID',


handler_name varchar(32) DEFAULT NULL COMMENT 'handler 名称',


handler_id varchar(32) DEFAULT NULL COMMENT 'handler 主键 id',


prev_handler_id varchar(32) DEFAULT NULL,


next_handler_id varchar(32) DEFAULT NULL COMMENT '下一个 handler',


PRIMARY KEY (ID)


) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT='权限表';


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码




-- Records of gateway_handler




INSERT INTO gateway_handler VALUES ('16', 'Api 接口限流', 'currentLimitHandler', null, 'blacklistHandler');


INSERT INTO gateway_handler VALUES ('17', '黑名单拦截', 'blacklistHandler', 'currentLimitHandler', 'conversationHandler');


INSERT INTO gateway_handler VALUES ('18', '会话验证', 'conversationHandler', 'blacklistHandler', null);


Utils


=========


@Component


public class SpringUtils implements ApplicationContextAware {


private static ApplicationContext applicationContext;


@Override


public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {


this.applicationContext = applicationContext;


}


//获取 applicationContext


public static ApplicationContext getApplicationContext() {


return applicationContext;


}


//通过 name 获取 Bean.


public static Object getBean(String name){


return getApplicationContext().getBean(name);


}


//通过 class 获取 Bean.


public static <T> T getBean(Class<T> clazz){


return getApplicationContext().getBean(clazz);


}


//通过 name,以及 Clazz 返回指定的 Bean


public static <T> T getBean(String name,Class<T> clazz){


return getApplicationContext().getBean(name, clazz);


}


}


GatewayHandlerService


=========================


/**


  • @title: GatewayHandlerService


*/


@Service


public class GatewayHandlerService {


@Autowired


private GatewayHandlerMapper gatewayHandlerMapper;


private GatewayHandler firstGatewayHandler;


/**


  • 获取数据库第一个 handeler 封装


*/


public GatewayHandler getFirstGatewayHandler() {


if (firstGatewayHandler != null) {


return firstGatewayHandler;


}


//1.【第一个实体】


GatewayHandlerEntity firstGatewayHandlerEntity = gatewayHandlerMapper.getFirstGatewayHandler();


if(firstGatewayHandlerEntity==null){ return null; }


//2.【第一个 HandlerId】


String firstHhandlerId = firstGatewayHandlerEntity.getHandlerId();


//3.【第二个 HandlerId】


String secondHandlerId = firstGatewayHandlerEntity.getNextHandlerId();


//4.【第一个 bean 对象】


GatewayHandler firstGatewayHandler = SpringUtils.getBean(firstHhandlerId, GatewayHandler.class);


//5.【tmpHandler 为第一个 bean 对象】


GatewayHandler tmpHandler=firstGatewayHandler;


//如果下一个 HandlerId 不为 null,则继续


while (!StringUtils.isBlank(secondHandlerId)){


//6.【第二个 bean 对象】->11.【第三个 bean 对象】


GatewayHandler secondGatewayHandler = SpringUtils.getBean(secondHandlerId, GatewayHandler.class);


//7.【设置第一个 bean 对象的 next 为第二个 bean 对象】->12.【设置第二个 bean 对象的 next 为第三个 bean 对象】


tmpHandler.setNextGatewayHandler(secondGatewayHandler);


//8.【第二个实体】->13.【第三个实体】


GatewayHandlerEntity secondHandlerEntity = gatewayHandlerMapper.getByHandler(secondHandlerId);


if (secondHandlerEntity==null){ break; }


//9.【第三个 HandlerId】->14.【第四个 HandlerId】此时为 null,后面会退出循环


secondHandlerId=secondHandlerEntity.getNextHandlerId();


//10.【tmpHandler 为第二个 bean 对象】->15.【tmpHandler 为第三个 bean 对象】


tmpHandler=secondGatewayHandler;


}


//16.赋值


this.firstGatewayHandler=firstGatewayHandler;


//17.返回第一个 firstHandler 对象


return firstGatewayHandler;


}


}


数据库访问层


GatewayHandlerMapper


public interface GatewayHandlerMapper {


/**


  • 获取第一个 GatewayHandler


*/


@Select("SELECT handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid FROM gateway_handler WHERE prev_handler_id is null;;")


public GatewayHandlerEntity getFirstGatewayHandler();


@Select("SELECT handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid FROM gateway_handler WHERE handler_id=#{handlerId}")


public GatewayHandlerEntity getByHandler(String handlerId);


}


Entity 层


@Data


public class GatewayHandlerEntity implements Serializable, Cloneable {


/**


  • 主键 ID


*/


private Integer id;


/**


  • handler 名称


*/


private String handlerName;


/**


  • handler 主键 id


*/


private String handlerId;


/**


  • 下一个 handler


*/


private String nextHandlerId;


}


Controller 层


/**


  • @title: HandlerController


*/


@RestController


public class HandlerController {


@Autowired


private GatewayHandlerService gatewayHandlerService;


@RequestMapping("/client")


public String client() {


GatewayHandler firstGatewayHandler = gatewayHandlerService.getFirstGatewayHandler();


firstGatewayHandler.service();


return "success";


}


}


相关配置信息


==========


版权 @须臾之余


https://my.oschina.net/u/3995125


application.yml


###服务启动端口号


server:


port: 8080

评论

发布
暂无评论
如何给网关设计一款专属的权限控制「责任链设计模式」(1)