IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    spring cloud java反向代理访问阿里云OSS私有资源

    hpkaiq发表于 2023-04-17 20:43:10
    love 0

    最近用到阿里云oss,有阿里云服务器,通过代理内网访问可以实现免除OSS流量费,查到很多nginx反向代理的教程,但是纯java实现没有找到,感觉可以试一试。

    (一) 首先要解决反向代理的问题,搜到org.mitre.dsmiley.httpproxy.ProxyServlet可解决。

    1
    2
    3
    4
    5
    
    <dependency>
       <groupId>org.mitre.dsmiley.httpproxy</groupId>
       <artifactId>smiley-http-proxy-servlet</artifactId>
       <version>1.11</version>
    </dependency>
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    @Configuration
    public class MyConfig {
        @Bean
        public ServletRegistrationBean servletRegistrationAliBean01() {
    
            ServletRegistrationBean oss  = new ServletRegistrationBean(new ProxyServlet(), "/ali/bucket_name/*");//修改为自己的bucket_name
            oss.setName("bucket_name");
            oss.addInitParameter("targetUri", "http://bucket_name.oss-cn-beijing.aliyuncs.com");//本地测试环境用外网地址,线上改成内网访问的地址
            oss.addInitParameter(ProxyServlet.P_LOG, "true");
            return oss;
        }
    
    }
    

    (二) Controller配置如下,转发到自己配置的反向代理

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    @RestController
    @RefreshScope
    @RequestMapping("/api/es")
    public class TestController {
         @RequestMapping("/static/**")
        public void testVideoOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, URISyntaxException {
            String resourcePath = request.getRequestURI().replace("/api/es/static","");
            HeaderUtil.setHeaderOwn(request,resourcePath);
            request.getRequestDispatcher("/ali" + resourcePath).forward(request, response);
        }
    }
    

    (三) 其中为request设置Header以认证OSS访问的HeaderUtil如下,其中有OSS Authorization计算的java实现,用java的反射在request中添加Header信息。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    
    
    import org.apache.commons.codec.binary.Base64;
    import org.apache.tomcat.util.http.MimeHeaders;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Field;
    import java.net.URISyntaxException;
    import java.nio.charset.Charset;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    import java.util.TimeZone;
    
    public class HeaderUtil {
        /**
         * 给request加入Header信息,验证OSS访问权限
         * @param request
         * @throws URISyntaxException
         */
        public static void setHeaderOwn(HttpServletRequest request,String resourcePath) throws URISyntaxException {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date_GMT = sdf.format(new Date());
            String data = request.getMethod() + "\n"
                    + "\n"
                    + "\n"
                    + date_GMT + "\n"
                    + resourcePath;
            String signature = genHMAC("AccessKeySecret", data);//AccessKeySecret改成自己的
            reflectSetParam(request, "Authorization", "OSS AccessKeyId:" + signature);//AccessKeyId改成自己的
            reflectSetParam(request, "Date", date_GMT);
        }
    
        /**
         * 反射修改header信息,key-value键值对加入到header中
         *
         * @param request
         * @param key
         * @param value
         */
        private static void reflectSetParam(HttpServletRequest request, String key, String value) {
            Class<? extends HttpServletRequest> requestClass = request.getClass();
            // System.out.println("request实现类="+requestClass.getName());
            try {
                Field request1 = requestClass.getDeclaredField("request");
                request1.setAccessible(true);
                Object o = request1.get(request);
                Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
                coyoteRequest.setAccessible(true);
                Object o1 = coyoteRequest.get(o);
                // System.out.println("coyoteRequest实现类="+o1.getClass().getName());
                Field headers = o1.getClass().getDeclaredField("headers");
                headers.setAccessible(true);
                MimeHeaders o2 = (MimeHeaders) headers.get(o1);
                o2.addValue(key).setString(value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * HmacSHA1 Base64加密
         * @param key
         * @param data
         * @return
         */
        public static String genHMAC(String key, String data) {
            byte[] result = null;
            try {
                //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
                SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                //生成一个指定 Mac 算法 的 Mac 对象
                Mac mac = Mac.getInstance("HmacSHA1");
                //用给定密钥初始化 Mac 对象
                mac.init(signinKey);
                //完成 Mac 操作
                byte[] rawHmac = mac.doFinal(data.getBytes(Charset.forName("UTF-8")));
                result = Base64.encodeBase64(rawHmac);
    
            } catch (NoSuchAlgorithmException e) {
                System.err.println(e.getMessage());
            } catch (InvalidKeyException e) {
                System.err.println(e.getMessage());
            }
            if (null != result) {
                return new String(result);
            } else {
                return null;
            }
        }
    }
    

    最后访问的地址例如: http://127.0.0.1:8081/api/es/static/bucket_name/object_name 可以加个拦截器做个登陆验证。



沪ICP备19023445号-2号
友情链接