JDK里面有一个java.security.MessageDigest类,这个类就是用来加密的。
String token = System.currentTimeMillis()+new Random().nextInt()+"";<img id="selectsearch-icon" src="https://gss0.bdstatic.com/70cFsjip0QIZ8tyhnq/img/iknow/qb/select-search.png" alt="搜索" class="selectsearch-hide">
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5 = md.digest(token.getBytes());
} catch (Exception e) {
throw new RuntimeException(e);
}
⑵ javaweb防止表单重复提交的几种解决方案
1.js方法解决:关于js方法解决就是说通过js动态控制提交按钮不能多次点击,或者多次点击不起作用。
方案一:通过设立标识使表单不能重复提交:
要强调的是,利用session方法解决表单重复问题是十分完美的,基本上可以应对各种重复提交问题。
但!是不是之前在客户端防止表单重复提交的种种方法就不使用了呢?
答案是否定的,我们需要多种方法混合使用才能达到最好的效果,也许有人会问,不是说session方法基本可以应对各种重复提交问题了吗?
这里我们所说的达到最好效果指的是,给用户更好地体验,例如用户点击了提交按钮,这时将按钮变为不可用的,用以告诉用户你已经提交内容了,不可重复提交。还有如果无论什么情况都用session防止表单重复提交问题,反而无形的增加了服务器端的负担。
⑶ 怎么用java调用微信支付接口
java调用微信支付接口方法:
RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse());
//获取 //两小时内有效,两小时后重新获取
Token = requestHandler.GetToken();
//更新token 到应用中
requestHandler.getTokenReal();
System.out.println("微信支付获取token=======================:" +Token);
//requestHandler 初始化
requestHandler.init();
requestHandler.init(appid,appsecret, appkey,partnerkey, key);
// --------------------------------本地系统生成订单-------------------------------------
// 设置package订单参数
SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("bank_type", "WX"); // 支付类型
packageParams.put("body", "xxxx"); // 商品描述
packageParams.put("fee_type", "1"); // 银行币种
packageParams.put("input_charset", "UTF-8"); // 字符集
packageParams.put("notify_url", "http://xxxx.com/xxxx/wxcallback"); // 通知地址 这里的通知地址使用外网地址测试,注意80端口是否打开。
packageParams.put("out_trade_no", no); // 商户订单号
packageParams.put("partner", partenerid); // 设置商户号
packageParams.put("spbill_create_ip", super.getRequest().getRemoteHost()); // 订单生成的机器IP,指用户浏览器端IP
packageParams.put("total_fee", String.valueOf(rstotal)); // 商品总金额,以分为单位
// 设置支付参数
SortedMap<String, String> signParams = new TreeMap<String, String>();
signParams.put("appid", appid);
signParams.put("noncestr", noncestr);
signParams.put("traceid", PropertiesUtils.getOrderNO());
signParams.put("timestamp", timestamp);
signParams.put("package", packageValue);
signParams.put("appkey", this.appkey);
// 生成支付签名,要采用URLENCODER的原始值进行SHA1算法!
String sign ="";
try {
sign = Sha1Util.createSHA1Sign(signParams);
} catch (Exception e) {
e.printStackTrace();
}
// 增加非参与签名的额外参数
signParams.put("sign_method", "sha1");
signParams.put("app_signature", sign);
// api支付拼包结束------------------------------------
//获取prepayid
String prepayid = requestHandler.sendPrepay(signParams);
System.out.println("prepayid :" + prepayid);
// --------------------------------生成完成---------------------------------------------
//生成预付快订单完成,返回给android,ios 掉起微信所需要的参数。
SortedMap<String, String> payParams = new TreeMap<String, String>();
payParams.put("appid", appid);
payParams.put("noncestr", noncestr);
payParams.put("package", "Sign=WXPay");
payParams.put("partnerid", partenerid);
payParams.put("prepayid", prepayid);
payParams.put("appkey", this.appkey);
//这里除1000 是因为参数长度限制。
int time = (int) (System.currentTimeMillis() / 1000);
payParams.put("timestamp",String.valueOf(time));
System.out.println("timestamp:" + time);
//签名
String paysign ="";
try {
paysign = Sha1Util.createSHA1Sign(payParams);
} catch (Exception e) {
e.printStackTrace();
}
payParams.put("sign", paysign);
//拼json 数据返回给客户端
BasicDBObject backObject = new BasicDBObject();
backObject.put("appid", appid);
backObject.put("noncestr", payParams.get("noncestr"));
backObject.put("package", "Sign=WXPay");
backObject.put("partnerid", payParams.get("partnerid"));
backObject.put("prepayid", payParams.get("prepayid"));
backObject.put("appkey", this.appkey);
backObject.put("timestamp",payParams.get("timestamp"));
backObject.put("sign",payParams.get("sign"));
String backstr = dataObject.toString();
System.out.println("backstr:" + backstr);
return backstr;
====================到此为止,预付款订单已生成,并且已返回客户端====================
//坐等微信服务器通知,通知的地址就是生成预付款订单的notify_url
ResponseHandler resHandler = new ResponseHandler(request, response);
resHandler.setKey(partnerkey);
//创建请求对象
//RequestHandler queryReq = new RequestHandler(request, response);
//queryReq.init();
if (resHandler.isTenpaySign() == true) {
//商户订单号
String out_trade_no = resHandler.getParameter("out_trade_no");
System.out.println("out_trade_no:" + out_trade_no);
//财付通订单号
String transaction_id = resHandler.getParameter("transaction_id");
System.out.println("transaction_id:" + transaction_id);
//金额,以分为单位
String total_fee = resHandler.getParameter("total_fee");
//如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee
String discount = resHandler.getParameter("discount");
//支付结果
String trade_state = resHandler.getParameter("trade_state");
//判断签名及结果
if ("0".equals(trade_state)) {
//------------------------------
//即时到账处理业务开始
//------------------------------
System.out.println("----------------业务逻辑执行-----------------");
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
System.out.println("----------------业务逻辑执行完毕-----------------");
System.out.println("success"); // 请不要修改或删除
System.out.println("即时到账支付成功");
//给财付通系统发送成功信息,财付通系统收到此结果后不再进行后续通知
resHandler.sendToCFT("success");
//给微信服务器返回success 否则30分钟通知8次
return "success";
}else{
System.out.println("通知签名验证失败");
resHandler.sendToCFT("fail");
response.setCharacterEncoding("utf-8");
}
}else {
System.out.println("fail -Md5 failed");
⑷ java 中如何进行md5加密
JDK里面有一个java.security.MessageDigest类,这个类就是用来加密的。
Stringtoken=System.currentTimeMillis()+newRandom().nextInt()+"";<img id="selectsearch-icon"src="https://gss0.bdstatic.com/70cFsjip0QIZ8tyhnq/img/iknow/qb/select-search.png"alt="搜索"class="selectsearch-hide">
try{
MessageDigestmd=MessageDigest.getInstance("MD5");
byte[]md5=md.digest(token.getBytes());
}catch(Exceptione){
thrownewRuntimeException(e);
}
⑸ 密码那些事
之前在工作中经常用密钥,但是不知道其中的原因,现在闲下来就来看下,再看的过程发现这个随机数概念很模糊,于是就查了下,现总结如下:
0x01 随机数
概述
随机数在计算机应用中使用的比较广泛,最为熟知的便是在密码学中的应用。本文主要是讲解随机数使用导致的一些Web安全风。
我们先简单了解一下随机数
分类
随机数分为真随机数和伪随机数,我们程序使用的基本都是伪随机数,其中伪随机又分为强伪随机数和弱伪随机数。
真随机数,通过物理实验得出,比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等
伪随机数,通过一定算法和种子得出。软件实现的是伪随机数
强伪随机数,难以预测的随机数
弱伪随机数,易于预测的随机数
特性
随机数有3个特性,具体如下:
随机性:不存在统计学偏差,是完全杂乱的数列
不可预测性:不能从过去的数列推测出下一个出现的数
不可重现性:除非将数列本身保存下来,否则不能重现相同的数列
随机数的特性和随机数的分类有一定的关系,比如,弱伪随机数只需要满足随机性即可,而强位随机数需要满足随机性和不可预测性,真随机数则需要同时满足3个特性。
引发安全问题的关键点在于不可预测性。
伪随机数的生成
我们平常软件和应用实现的都是伪随机数,所以本文的重点也就是伪随机数。
伪随机数的生成实现一般是算法+种子。
具体的伪随机数生成器PRNG一般有:
线性同余法
单向散列函数法
密码法
ANSI X9.17
比较常用的一般是线性同余法,比如我们熟知的C语言的rand库和Java的java.util.Random类,都采用了线性同余法生成随机数。
应用场景
随机数的应用场景比较广泛,以下是随机数常见的应用场景:
验证码生成
抽奖活动
UUID生成
SessionID生成
Token生成
CSRF Token
找回密码Token
游 戏 (随机元素的生成)
洗牌
俄罗斯方块出现特定形状的序列
游戏爆装备
密码应用场景
生成密钥:对称密码,消息认证
生成密钥对:公钥密码,数字签名
生成IV: 用于分组密码的CBC,CFB和OFB模式
生成nonce: 用于防御重放攻击; 分组密码的CTR模式
生成盐:用于基于口令的密码PBE等
0x02 随机数的安全性
相比其他密码技术,随机数很少受到关注,但随机数在密码技术和计算机应用中是非常重要的,不正确的使用随机数会导致一系列的安全问题。
随机数的安全风险
随机数导致的安全问题一般有两种
应该使用随机数,开发者并没有使用随机数;
应该使用强伪随机数,开发者使用了弱伪随机数。
第一种情况,简单来讲,就是我们需要一个随机数,但是开发者没有使用随机数,而是指定了一个常量。当然,很多人会义愤填膺的说,sb才会不用随机数。但是,请不要忽略我朝还是有很多的。主要有两个场景:
开发者缺乏基础常识不知道要用随机数;
一些应用场景和框架,接口文档不完善或者开发者没有仔细阅读等原因。
比如找回密码的token,需要一个伪随机数,很多业务直接根据用户名生成token;
比如OAuth2.0中需要第三方传递一个state参数作为CSRF Token防止CSRF攻击,很多开发者根本不使用这个参数,或者是传入一个固定的值。由于认证方无法对这个值进行业务层面有效性的校验,导致了 OAuth 的CSRF攻击。
第二种情况,主要区别就在于伪随机数的强弱了,大部分(所有?)语言的API文档中的基础库(常用库)中的random库都是弱伪随机,很多开发自然就直接使用。但是,最重要也最致命的是,弱伪随机数是不能用于密码技术的。
还是第一种情况中的找回密码场景,关于token的生成, 很多开发使用了时间戳作为随机数(md5(时间戳),md5(时间戳+用户名)),但是由于时间戳是可以预测的,很容易就被猜解。不可预测性是区分弱伪随机数和强伪随机数的关键指标。
当然,除了以上两种情况,还有一些比较特别的情况,通常情况下比较少见,但是也不排除:
种子的泄露,算法很多时候是公开的,如果种子泄露了,相当于随机数已经泄露了;
随机数池不足。这个严格来说也属于弱伪随机数,因为随机数池不足其实也导致了随机数是可预测的,攻击者可以直接暴力破解。
漏洞实例
wooyun上有很多漏洞,还蛮有意思的,都是和随机数有关的。
1.应该使用随机数而未使用随机数
Oauth2.0的这个问题特别经典,除了wooyun实例列出来的,其实很多厂商都有这个问题。
Oauth2.0中state参数要求第三方应用的开发者传入一个CSRF Token(随机数),如果没有传入或者传入的不是随机数,会导致CSRF登陆任意帐号:
唯品会账号相关漏洞可通过csrf登录任意账号
人人网 - 网络 OAuth 2.0 redirect_uir CSRF 漏洞
2.使用弱伪随机数
1) 密码取回
很多密码找回的场景,会发 送给 用户邮件一个url,中间包含一个token,这个token如果猜测,那么就可以找回其他用户的密码。
1. Shopex 4.8.5密码取回处新生成密码可预测漏洞
直接使用了时间函数microtime()作为随机数,然后获取MD5的前6位。
1. substr(md5(print_r(microtime(),true)),0,6);
PHP 中microtime()的值除了当前 服务器 的秒数外,还有微秒数,微妙数的变化范围在0.000000 -- 0.999999 之间,一般来说,服务器的时间可以通过HTTP返回头的DATE字段来获取,因此我们只需要遍历这1000000可能值即可。但我们要使用暴力破解的方式发起1000000次请求的话,网络请求数也会非常之大。可是shopex非常贴心的在生成密码前再次将microtime() 输出了一次:
1. $messenger = &$this->system->loadModel('system/messenger');echo microtime()."
";
2.奇虎360任意用户密码修改
直接是MD5( unix 时间戳)
3.涂鸦王国弱随机数导致任意用户劫持漏洞,附测试POC
关于找回密码随机数的问题强烈建议大家参考拓哥的11年的文章《利用系统时间可预测破解java随机数| 空虚浪子心的灵魂》
2) 其他随机数验证场景
CmsEasy最新版暴力注入(加解密缺陷/绕过防注入)
弱伪随机数被绕过
Espcms v5.6 暴力注入
Espcms中一处SQL注入漏洞的利用,利用时发现espcms对传值有加密并且随机key,但是这是一个随机数池固定的弱伪随机数,可以被攻击者遍历绕过
Destoon B2B 2014-05-21最新版绕过全局防御暴力注入(官方Demo可重现)
使用了microtime()作为随机数,可以被预测暴力破解
Android 4.4之前版本的Java加密架构(JCA)中使用的Apache Harmony 6.0M3及其之前版本的SecureRandom实现存在安全漏洞,具体位于classlib/moles/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
类的engineNextBytes函数里,当用户没有提供用于产生随机数的种子时,程序不能正确调整偏移量,导致PRNG生成随机序列的过程可被预测。
Android SecureRandom漏洞详解
安全建议
上面讲的随机数基础和漏洞实例更偏重是给攻击者一些思路,这里更多的是一些防御和预防的建议。
业务场景需要使用随机数,一定要使用随机数,比如Token的生成;
随机数要足够长,避免暴力破解;
保证不同用处的随机数使用不同的种子
对安全性要求高的随机数(如密码技术相关)禁止使用的弱伪随机数:
不要使用时间函数作为随机数(很多程序员喜欢用时间戳) Java:system.currenttimemillis() php:microtime()
不要使用弱伪随机数生成器 Java: java.util.Random PHP: rand() 范围很小,32767 PHP: mt_rand() 存在缺陷
强伪随机数CSPRNG(安全可靠的伪随机数生成器(Cryptographically Secure Pseudo-Random Number Generator)的各种参考
6.强伪随机数生成(不建议开发自己实现)
产生高强度的随机数,有两个重要的因素:种子和算法。算法是可以有很多的,通常如何选择种子是非常关键的因素。 如Random,它的种子是System.currentTimeMillis(),所以它的随机数都是可预测的, 是弱伪随机数。
强伪随机数的生成思路:收集计算机的各种,键盘输入时间,内存使用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,主要是达到不可预测性。
暂时先写到这里
⑹ java一键登录discuz PHP论坛
小弟目前实现这个,有两个办法。第一个,是用户再点击登陆的时候给他加上一层遮罩,让他不可以点别的了。第二个,就是用struts2的单点登录,页面配置token。这是两个想法,你可以从这两方面入手。你上面说的什么md5,没听明白这跟单点登陆有什么关系,单点登陆是防止用户重复提交的