自建加密解密传输&kaptcha验证码使用次数限制思路

xiaoxiao2021-03-01  9

序:       刚来第一天环境刚搞好,svn刚装完,账号都还没有,员工手册还没有学习完,就被要求开始撸代码。还好同事之间沟通狠顺畅,直接可以找到人问东西。      今天主要比较紧急的待修复项:      1.验证码只能使用一次的问题      2.登录/修改密码过程中数据传输简单的decode不满足安全性要求      首先说下这边的验证码是怎么生成的。一般我们已说到验证码只能用一次想到的肯定是利用redis存储生成的验证码,设置时效性。但是这里生成验证码用的是一个组件kaptcha,这个组件的核心思路就是生成了验证码放session里,没有设置有效时长这个说法。此外异步校验也是每次从session取比对,代码如下:    String  captchaCode = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);         if(captchaCode.equalsIgnoreCase(verificationCode)){             return "true";         }      如果比对一致就表示校验通过。这里权限是使用shiro,登陆也校验验证码,这时候是从token里取比对。重点来了,我处理这里保证验证码只能使用一次也是在这里做的逻辑,也就是在shiro的继承AuthorizingRealm里的doGetAuthenticationInfo方法里做文章,思路:就是在校验token里的验证码比对时从session删除验证码,这样再次传这个验证码就过不了了,具体逻辑: String captcha = (String) SecurityUtils                 .getSubject()                 .getSession()                 .getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);

//删除session里的验证码         SecurityUtils.getSubject().getSession().removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);         if(StringUtils.isBlank(captcha)) {             throw new IncorrectCaptchaException("验证码失效");         } //比对token里与session里的验证码         if (captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha()) ){             throw new IncorrectCaptchaException("验证码错误");         } 另外做以上操作,注意需要配合页面的刷新做,比如页面提示验证失效或错误了需要重新获取ajax生成(保证新生成一个放session里备用)      接下来该说第二个问题,那就是加密传输的问题。      其实这里的思路受起来也狠简单,就是传统的加密配合自己写的加密使用。自己写的加密的思路:      每个输入的字符生成一个的字符串,而这个字符串里某位是角标,真正的charAt(角标)位置才是输入内容,其他位则是随机生成,这个角标也是随机的,所以生成的串每次看起来不一样,这样抓到的包看到的就是每次发送的都不一样,让黑客难以分析出规律。前台自建加密js: function randomsort(d, c) {     return Math.random() > 0.5 ? -1 : 1 } function encryption(e) {     var g = e.split("");     for (var f = 0; f < g.length; f++) {         var h = Math.floor(Math.random() * 3) + 1;         var c = (f + 1) + "0" + (h + 1);         for (var d = 0; d < h; d++) {             c += Math.floor(Math.random() * 9)         }         g[f] = c + g[f];         var b = 9 - g[f].length;         if (b > 2) {             for (d = 0; d < b; d++) {                 g[f] += Math.floor(Math.random() * 9)             }         }     }     g.sort(randomsort);     var a = "";     for (f = 0; f < g.length; f++) {         a += g[f] + "$"     }     return a }; 页面使用也超级简单: var username = encode(encryption($("#username").val()));    $("#sendUsername").val(username); var password = encode(encryption($("#password").val())); $("#sendPassword").val(password); 其实就是获取用户输入的明文进行自建加密,然后再调用一次其他常规加密,这里的encode就是其他的常规加密。 这样因为自建加密生成的串随机,那么常规加密生成的就每次不一样,尽管真正的每次用户名密码都一样。 但是说实话,别人要是花店心思先获取这个自建加密js(浏览器打开debug就可以看到,不过这个js要想让用户看到但是不知道什么意思除了变量定义用abcd外还可以加混淆,这样真的绝大部分黑客就望而止步了),说远了。 再来说说后台的解密,其实根据这个js已经可以知道java的解密怎么写了,这里贴出的我故意留个bug吧,可以用,但是会有问题,不能告诉大家见谅,如果真需要知道,可以单独找我。 public static String decryp(String str){         String[] strs = str.split("[$]");         Map<Integer, String> map = new TreeMap<Integer, String>(                 new Comparator<Integer>() {                     public int compare(Integer obj1, Integer obj2) {                         return obj2.compareTo(obj1);                     }          });         for(String temp : strs){             Integer number = Integer.parseInt(temp.substring(0, temp.indexOf("0")));             temp = temp.substring(temp.indexOf("0") + 1, temp.length());             Integer index = Integer.parseInt(temp.substring(0, 1));             String[] temps = temp.split("");             String value = temps[index];             map.put(number, value);         }         Set<Integer> keySet = map.keySet();         Iterator<Integer> iter = keySet.iterator();         String result = "";         while (iter.hasNext()) {             Integer key = iter.next();             result = map.get(key) + result;         }         return result;     } 这是自建加密的后台解密,常规加密的解密就不说了。 到此私密数据的安全传输就提高一个档次了,加个混淆安全性就更上一层楼了。

 

转载请注明原文地址: https://www.6miu.com/read-4149958.html

最新回复(0)