最近公司有一个小需求,所有的图片都是储存在阿里云的oss服务器上,现在要通过浏览器能够访问这些图片资源,并且需要将过期的会话和非法的连接排除掉。目前配合白名单能够实现基本的安全认证,但也还仅是个demo,仍然存在很多性能和安全的问题。需求很简单:
String pw = "密钥"; //This class specifies an initialization vector (IV). Examples which use IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation. byte[] ivBytes = "初始化向量,不是很懂IvParameterSpec的作用,但是看上面官方解释,意思是初始化向量" Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec key = new SecretKeySpec(pw.getBytes(), "AES"); IvParameterSpec iv = new IvParameterSpec(ivBytes); aesCBC.init(Cipher.ENCRYPT_MODE, key, iv);
class OpenSslAES {
public static byte[] encrypt(byte[] data) {
return aesCBC.doFinal(data); //aesCBC为1.1代码中生成的密码机
}
}
public static String encrypt(){ String content = String.format("{\"last_alive_time\":%s}", System.currentTimeMillis()); try { byte[] result = OpenSslAES.encrypt(content.getBytes()); return bytesToHex(result); } catch (Exception e) { throw new RESTFulTradeErrorCodeException(ManagementErrorCode.ENCRYPT_ERROR.getCode(), e, ManagementErrorCode.ENCRYPT_ERROR.getErrMessage()); } }
private static String str[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
static String bytesToHex(byte[] ch) {
StringBuilder ret = new StringBuilder("");
for (int i = 0; i < ch.length; i++){
ret.append(str[ch[i] >> 4 & 0xF] + str[ch[i] & 0xF]);
}
return ret.toString();
}
location /images_proxy {
default_type text/html;
lua_code_cache on;
access_by_lua_file /nginx/lualib/aeslua/aeslua.lua;
}
需要实现安装openresty
local aes = require "resty.aes"
local cjson = require "cjson"local hash = {
iv = "与上述Java程序中的iv值保持一致",
method = nil
}
local salt = "1234567890"
local aes_128_cbc, err = aes:new("与上述Java程序中的pw密钥的值保持一致", salt, aes.cipher(128, "cbc"), hash)
if err then
ngx.say(err)
ngx.exit(200) //如果创建AES密码机失败,则返回
end//该函数用户将十六进制字符串转化为二进制,在lua中好像没有字节数组的数据类型,所以这里直接拼接字符串
function hex_to_str(str)
return (str:gsub('..', function(cc)
return string.char(tonumber(cc, 16))
end))
end//从cookie中获取session_login,如果不存在,则说明用户未登录,直接返回
local session_str = ngx.var.cookie_session_login
if session_str == nil then
ngx.say("not login.")
ngx.exit(401)
return
end//将获取到的cookie以json进行处理,如果其中last_alive_time的值不存在或者超期,则直接返回
session_json=cjson.decode(session_info)
if session_json == nil or session_json['last_alive_time']==nil then
ngx.say("not login.")
ngx.exit(401)
return
end
if ngx.now()*1000-session_json['last_alive_time'] > 300000 then
ngx.say("login expired.")
ngx.exit(401)
return
end
//仅允许GET请求,其他一切method方式全部返回
local action = ngx.var.request_mthod;
if action == "POST" then
ngx.say("only support GET!");
ngx.exit(403);
return;
end
//创建http客户端,并尝试访问图片资源服务
local http = require "resty.http";
local httpc = http.new();local res,err = httpc:request_uri("图片服务器域名 + 原请求中的图片路径,例如/2018/11/1.jpg",{ method ="GET"});
ngx.header.content_type="image/gif";
//如果访问图片服务器失败,则返回本地一张默认图片,否则就将从图片服务器读取到的数据返回回去
if err then
local f = io.open("/nginx/html/image-not-found.png", "rb");
local content = f:read("*all");
f:close();
ngx.print(content);
else
ngx.print(res.body);
end