【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(二)

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南

【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(一)https://developer.aliyun.com/article/1470989


实现案例

定义鉴权服务中心服务
建立Dubbo3的服务容器作为鉴权服务实现

Undertow容器处理功能,用于接收对应的Http鉴权请求接口服务,用于处理来资源服务提供者端的Http请求。

数据模型



定义对应的实现鉴权中心鉴权匹配实现类

定义Hutools的数据源DB

在对应的resources下的config文件下建立db.setting文件,之后配置对应的数据源

ini

复制代码

#中括表示一个分组,其下面的所有属性归属于这个分组,在此分组名为ds1,也可以没有分组
[ds1]
#自定义数据源设置文件,这个文件会针对当前分组生效,用于给当前分组配置单独的数据库连接池参数,没有则使用全局的配置
driver = com.mysql.jdbc.Driver
#JDBC url,必须
url = jdbc:mysql://127.0.0.1:3306/dubbo-shopping
#用户名,必须
user = root
#密码,必须,如果密码为空,请填写 pass =
pass = root$
实现查询数据库的Hutool操作

java

复制代码

List<Entity> authData = Db.use(dataSource).query("select * from auth_data");
if(CollectionUtil.isNotEmpty(authData)){
  Entity entity = authData.get(0);
  String ak = entity.getStr("ak");
  String sk = entity.getStr("sk");
}
实现传递过来的数据库的Hutool操作

java

复制代码

@Data
@Slf4j
@NoArgsConstructor
public class AuthService {
    DataSource dataSource = DSFactory.get("ds1");
    /**
     * 匹配ak和sk的值
     * @param appCode
     * @param appKey
     * @param secretKey
     * @return
     */
    public boolean matchSecretKey(String appCode,String appKey,String secretKey){
        log.info("appCode:{} - local-appkey:{} - local-secretKey:{}",appCode,appKey,secretKey);
        if(StringUtils.isEmpty(appKey)){
            return Boolean.FALSE;
        }
        try {
            List<Entity> authData = Db.use(dataSource).query("select * from auth_data where code = ?",appCode);
            if(CollectionUtil.isNotEmpty(authData)){
                Entity entity = authData.get(0);
                String ak = entity.getStr("ak");
                String sk = entity.getStr("sk");
                log.info("remote-appkey:{} - remote-secretKey:{}",ak,sk);
                if(ak.equals(ak)){
                    if(StringUtils.isEmpty(sk)){
                        return Boolean.FALSE;
                    }
                    else if(!SecureUtil.md5(sk).equals(secretKey)){
                        return Boolean.FALSE;
                    }
                }else{
                    return Boolean.FALSE;
                }
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        } catch (SQLException e) {
            log.error("auth is error!",e);
            return Boolean.FALSE;
        }
    }
}

鉴权服务 UndertowContainer

采用Undertow容器服务机制,在之前的章节已经介绍和说明了如何实现对应的dubbo的自定义容器实现,在这里我们使用的是UndertowContainer。如果想要学习可以关注之前的文章章节。

java

复制代码

package com.hyts.assemble.dubbo3.comp.container;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import com.hyts.assemble.dubbo3.comp.auth.AuthService;
import io.undertow.Undertow;
import io.undertow.util.Headers;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.container.Container;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
public class UnderTowContainer implements Container {
    //定义容器端口
    public static final String UNDERTOW_PORT = "dubbo.undertow.port";
    //定义容器contextPath
    public static final String UNDERTOW_DEFAULT_PATH = "dubbo.undertow.path";
    
    private AuthService authService = new AuthService();
    
    //设置HttpHandler回调方法
   final Undertow server = Undertow.builder()
            .addHttpListener(NumberUtil.parseInt(ConfigurationUtils.getProperty(UNDERTOW_PORT)), "localhost")
            .setHandler(exchange -> {
                if(exchange.getRequestPath().equals(ConfigurationUtils.getProperty(UNDERTOW_DEFAULT_PATH))){
                    String appKey = String.valueOf(exchange.getQueryParameters().get("appKey").poll());
                    String secretKey = String.valueOf(exchange.getQueryParameters().get("secretKey").poll());
                    String appCode = String.valueOf(exchange.getQueryParameters().get("appCode").poll());
                    boolean result = authService.matchSecretKey(appCode,appKey,secretKey);
                    exchange.getResponseSender().send(String.valueOf(result));
                }
            }).build();
            
    // 定义启动方法        
    @Override
    public void start() {
        server.start();
    }
   
    // 定义停止方法 
    @Override
    public void stop() {
        server.stop();
    }
}

定义容器的dubbo.properties

ini

复制代码

dubbo.container=spring,jetty,log4j,undertow
dubbo.undertow.path=/auth
dubbo.undertow.port=8081
服务提供端

只需要设置 service.auth 为 true,表示该服务的调用需要鉴权认证通过。param.sign为true表示需要对参数也进行校验,之前的章节的内容我们已经介绍了对应的如何建立校验功能的实现机制控制。

java

复制代码

// (注解方式)
@DubboService(parameters = {"service.auth","true"})
public class AuthServiceImpl implements AuthService {
}

xml

复制代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>
    <dubbo:application name="direct-consumer"/>
    <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181" check="false"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <bean id="rpcAuthSampleApi" class="com.dubbo.shopping.commodity.rpc.auth.AuthServiceImpl"/>
    <dubbo:service id="rpcAuthSampleApiHandler" interface="com.dubbo.shopping.commodity.api.AuthService"
                   ref="rpcAuthSampleApi" version="0.0.0" filter="auth">
      <dubbo:parameter key="service.auth" value="true"/>
</dubbo:service>
</beans>
服务提供端-建立服务鉴权过滤器

在之前的章节文章中介绍了对应的META-INF/dubbo下建立org.apache.dubbo.rpc.Filter文件,之后进行auth=com.dubbo.shopping.common.auth.filter.AuthFilter,之后会进行定义我们的authFilter过滤器实现类。

建立dubbo.properties配置信息读取相关的鉴权服务的地址

resources文件下建立dubbo.properties之后添加对应的内容

properties

复制代码

dubbo.auth.url=http://localhost:8081/auth

可以使用对应的配置工具进行获取配置信息。

java

复制代码

ConfigurationUtils.getProperty("dubbo.auth.url")

定义对应的服务提供端-建立服务鉴权过滤器

java

复制代码

@Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        boolean authNeed = Boolean.valueOf(invoker.getUrl().getParameter("service.auth"));
        String ak = invocation.getAttachment("AK");
        String sk = invocation.getAttachment("SK");
        String authUrl = ConfigurationUtils.getProperty("dubbo.auth.url");
        if(authNeed){
            log.info("PROCESS AUTH THE INVOKE!APPKEY {} , SECRETKEY {} : authUrl:{}",ak,sk,authUrl);
            String result = HttpUtil.get(authUrl+"?appCode="+"dubbo-shopping"+"&appKey="+ak+"&secretKey="+sk);
            if(!Boolean.valueOf(result)){
                log.error("NOT AUTH THE INVOKE! APPKEY {} , SECRETKEY {}",ak,sk);
                throw new RpcException("NOT AUTH THE INVOKE!");            }
        }
        log.info("PASS AUTH THE INVOKE!APPKEY {} , SECRETKEY {}",ak,sk);
//        if(paramSign){
//        }
        return invoker.invoke(invocation);
    }
服务消费端

只需要配置好对应的证书等信息即可,之后会自动地在对这些需要认证的接口发起调用前进行签名操作,通过与鉴权服务的交互,用户无需在代码中配置 AK/SK 这些敏感信息,并且在不重启应用的情况下刷新 AK/SK,达到权限动态下发的目的。

该方案目前已经提交给 Dubbo 开源社区,并且完成了基本框架的合并,除了 AK/SK 的鉴权方式之外,通过 SPI 机制支持用户可定制化的鉴权认证以及适配公司内部基础设施的密钥存储。

xml

复制代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder/>
    <dubbo:application name="direct-consumer"/>
    <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181" check="false"/>
    <dubbo:provider token="true"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:reference id="authSampleApi" check="false" interface="com.dubbo.shopping.commodity.api.AuthSampleApi" version="*"/>
</beans>
模拟远程调用

java

复制代码

package com.dubbo.shopping.commodity.controller;
import cn.hutool.crypto.SecureUtil;
import com.dubbo.shopping.commodity.api.AnnotationConstants;
import com.dubbo.shopping.commodity.api.AuthSampleApi;
import com.dubbo.shopping.commodity.api.CommodityQueryApi;
import com.dubbo.shopping.commodity.entity.BaseInfo;
import com.dubbo.shopping.commodity.model.CommodityQueryDTO;
import com.dubbo.shopping.model.rpc.RpcRequest;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * <p>
 * 商品主题信息 前端控制器
 * </p>
 *
 * @author libo
 * @since 2022-05-08
 */
@RestController
@RequestMapping("/commodity/base-info")
public class BaseInfoController {
    @Autowired
    AuthSampleApi authSampleApi;
    @ApiOperation("权限控制调用")
    @RequestMapping("/auth")
    public ResponseEntity auth(){
        RpcContext.getClientAttachment().setAttachment("AK","dubbo3");
        RpcContext.getClientAttachment().setAttachment("SK", SecureUtil.md5("123456"));
        return ResponseEntity.ok(authSampleApi.executeAuth("test parameter"));
    }
}

既可以实现鉴权服务机制,大家还可以自己进行扩展实现。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
2天前
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
【SpringCloud Alibaba系列】Dubbo高级特性篇
|
1月前
|
运维 安全 Linux
全面提升系统安全:禁用不必要服务、更新安全补丁、配置防火墙规则的实战指南
全面提升系统安全:禁用不必要服务、更新安全补丁、配置防火墙规则的实战指南
54 12
|
2月前
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
173 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
4月前
|
JSON Dubbo Java
【Dubbo协议指南】揭秘高性能服务通信,选择最佳协议的终极攻略!
【8月更文挑战第24天】在分布式服务架构中,Apache Dubbo作为一款高性能的Java RPC框架,支持多种通信协议,包括Dubbo协议、HTTP协议及Hessian协议等。Dubbo协议是默认选择,采用NIO异步通讯,适用于高要求的内部服务通信。HTTP协议通用性强,利于跨语言调用;Hessian协议则在数据传输效率上有优势。选择合适协议需综合考虑性能需求、序列化方式、网络环境及安全性等因素。通过合理配置,可实现服务性能最优化及系统可靠性提升。
67 3
|
4月前
|
C# 开发者 Windows
勇敢迈出第一步:手把手教你如何在WPF开源项目中贡献你的第一行代码,从选择项目到提交PR的全过程解析与实战技巧分享
【8月更文挑战第31天】本文指导您如何在Windows Presentation Foundation(WPF)相关的开源项目中贡献代码。无论您是初学者还是有经验的开发者,参与这类项目都能加深对WPF框架的理解并拓展职业履历。文章推荐了一些适合入门的项目如MvvmLight和MahApps.Metro,并详细介绍了从选择项目、设置开发环境到提交代码的全过程。通过具体示例,如添加按钮点击事件处理程序,帮助您迈出第一步。此外,还强调了提交Pull Request时保持专业沟通的重要性。参与开源不仅能提升技能,还能促进社区交流。
52 0
|
7月前
|
监控 安全 Linux
Linux系统的防御从多个方面来保护系统安全
防火墙:使用防火墙软件如iptables或Firewalld来限制网络流量,保护系统免受恶意网络攻击。
|
7月前
|
网络协议 安全 Linux
linux系统安全及应用——端口扫描
linux系统安全及应用——端口扫描
89 0
|
安全 Linux
Linux 系统安全 - 近期发现的 polkit pkexec 本地提权漏洞(CVE-2021-4034)修复方案
Linux 系统安全 - 近期发现的 polkit pkexec 本地提权漏洞(CVE-2021-4034)修复方案
1327 2
|
安全 网络协议 Unix
Linux系统安全与应用
系统安全问题一直存在着,当系统往往出现安全漏洞的时候会对我们的系统运行有一定程度的影响,严重的话还会造成系统瘫痪等问题。
Linux系统安全与应用
|
安全 网络协议 算法
Linux系统安全及应用
⭐本文介绍⭐ 作为一种开放源代码的操作系统,Linux服务器以其安全,高效和稳定的显著优势而得以广泛应用。本文主要从账号安全控制、系统引导和登录控制的角度,介绍Linux系统安全优化的点点滴滴;还将介绍基于Linux环境的弱口令检测、网络扫描等安全工具的构建和使用,帮助管理员查找安全隐患,及时采取有针对性的防护措施。
Linux系统安全及应用

热门文章

最新文章