通过openresty 解决遗留 webservice 接口安全问题

技术一直在变革,老的技术一般都会成为现在的技术债,加上早期大家一般对于安全不是很重视(尤其是在内网环境的时候),尽管webservice 是包含了
ws-security 安全指南的,但是很多时候大家不是很重视(而且这个规范稍晚),以下是一个简单的实践

参考图

 

 

原理简单说明

核心还是利用了openresty 的阶段处理能力,为了减少业务改造的成本我们可以直接使用影响小的基于header 以及基于ip 防护的处理策略

简单实践

  • 环境准备
    docker-compose.yaml
 
version: '3'
services:
   app:
     image: openresty/openresty:1.21.4.1-3-alpine-fat
     volumes:
     - "./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf"
     ports:
     - "80:80"

nginx.conf 配置

user root;  
worker_processes  1;
events {
    worker_connections  1024;
}
 
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '$http_token';
    include       mime.types;
    default_type  application/octet-stream;
    gzip  on;
    rewrite_log on;
    real_ip_header     X-Forwarded-For;
    server {
       listen 80;
       charset utf-8;
       default_type text/html;
       location / {
            access_by_lua_block {
                 -- 请求必须携带token,包括wsdl 文件,以及后续操作,实际可以集合认证机制
                 if ngx.req.get_headers()["token"] == nil  then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                 end
            }
            access_log  logs/access2.log  main;
            sub_filter http://www.dneonline.com 'http://localhost';
            sub_filter_types text/xml; 
            sub_filter_once off;
            proxy_set_header Accept-Encoding '';
           # 注意使用一个开放的webservice www.dneonline.com
            proxy_set_header Host www.dneonline.com;
            proxy_set_header X-Forwarded-For $remote_addr;
            client_body_buffer_size 10M;
            proxy_set_header X-Forwarded-Proto      $scheme;
            client_max_body_size 10G;
            proxy_buffers 1024 4k;
            proxy_read_timeout 300;
            proxy_pass http://www.dneonline.com;
       }
    }
}
  • api 调用
    使用了nodejs 的soap 包
 
var soap = require('soap');
var url = 'http://localhost/calculator.asmx?wsdl';
var args = {intA: 2,intB:3};
soap.createClient(url, {
    wsdl_options:{
        headers: {'token': 'mytoken'}, // wsdl 携带token
    }
}, function(err, client) {
    console.dir(client)
    client.addHttpHeader("token","mytoken") // 请求携带token
    client.Add(args, function(err, result) {
        console.log(result.AddResult);
    });
});
  • 效果

直接访问(因为没有token 会被拦截)

 

 


nginx 请求日志,包含了一个get 以及一个post 请求

 

 

node 应用效果

 

 

说明

以上是一个简单的集成,同时包含了如何使用nginx 进行webservice 的代理(核心是sub_filter 指令),对于webservice 的安全实际上问题还是不少的,可以参考
基于ip也是一种模式,header 各种语言的基本都是可以支持的,难度不大

参考资料

https://www.npmjs.com/package/soap
https://cxf.apache.org/docs/interceptors.html
https://github.com/rongfengliang/openresty-webservice-auth/tree/master

posted on 2022-08-13 12:27  荣锋亮  阅读(251)  评论(0编辑  收藏  举报

导航