一个微信投票小程序防止刷票的想法
简单介绍
最近公司有个项目,开发一个微信小程序,里面有个模块是投票。鉴于第一期投票活动被刷票虐的体无完肤,还是得进行总结与进步,尽量的加大刷票难度。
投票的流程中最重要的是验证功能,验证是否符合可以投票的条件。
设想的验证规则是:
- openid是否正确有效
- 图形验证码是否正确
- IP是否在黑名单内(这里就不讲了,缺点比较大,各种代理,一个IP进了黑名单,整个局域网的终端都不能投票了)
- 单一用户是否重复投票(这也不讲了,没啥好讲,大家都懂)
一、首先讲下登录
由小程序调用wx.login触发授权,获取到code值,code再作为请求参数调用后台接口,后台接口根据appid、secret、grant_type和这个code参数调用https://api.weixin.qq.com/sns/jscode2session这个接口获取openid并保存到数据库中,刷票的人无法用正确的code来获取openid,所以安全性相比之前大了许多(o(╥﹏╥)o),获取openid示例如下:
public static JSONObject getMessage(Object code){Object openid = null;Object unionid = null;JSONObject jsonObject = null;String outputStr = null;String url1 = "https://api.weixin.qq.com/sns/jscode2session?appid=你的appid&secret=你的secret&js_code=" + code+"&grant_type=authorization_code";StringBuffer buffer=null;try{//创建SSLContextSSLContext sslContext=SSLContext.getInstance("TLS");TrustManager[] tm={new MyX509TrustManager()};//初始化sslContext.init(null, tm, new java.security.SecureRandom());;//获取SSLSocketFactory对象SSLSocketFactory ssf=sslContext.getSocketFactory();URL url=new URL(url1);HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setRequestMethod("GET");//设置当前实例使用的SSLSoctetFactoryconn.setSSLSocketFactory(ssf);conn.connect();//往服务器端写内容 也就是发起http请求需要带的参数if(null!=outputStr){OutputStream os=conn.getOutputStream();os.write(outputStr.getBytes("utf-8"));os.close();}//读取服务器端返回的内容InputStream is=conn.getInputStream();InputStreamReader isr=new InputStreamReader(is,"utf-8");BufferedReader br=new BufferedReader(isr);buffer=new StringBuffer();String line=null;while((line=br.readLine())!=null){buffer.append(line);}jsonObject = JSONObject.parseObject(buffer.toString());System.out.println("debug:openIdUtils.getMessage=" + jsonObject);openid = jsonObject.get("openid");unionid = jsonObject.get("unionid");System.out.print("openid:"+openid);}catch(Exception e){e.printStackTrace();}return jsonObject; }
二、图形验证码
- 后台增加方法生成4位随机字母+数字的字符串,并生成对应图片的base64编码,将base64编码返回给微信小程序前端进行展示。
- 在确认投票的接口中对验证码进行校验是否有效。
以下是生成验证码的工具类代码:
package com.weixin.utils;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Random;import javax.imageio.ImageIO;import org.apache.commons.lang3.RandomUtils;import com.alibaba.druid.util.Base64;public class ValidateCodeUtil {private static Validate validate = null; //验证码类,用于最后返回此对象,包含验证码图片base64和真值private static Random random = new Random(); //随机类,用于生成随机参数private static String randString = "0123456789abcdefghijkmnpqrtyABCDEFGHIJLMNQRTY";//随机生成字符串的取值范围 private static int width = 80; //图片宽度 private static int height = 34; //图片高度 private static int StringNum = 4; //字符的数量 private static int lineSize = 40; //干扰线数量 //将构造函数私有化 禁止new创建private ValidateCodeUtil() {super();}/** * 获取随机字符,并返回字符的String格式 * @param index (指定位置) * @return */ private static String getRandomChar(int index) { //获取指定位置index的字符,并转换成字符串表示形式 return String.valueOf(randString.charAt(index)); } /*** 获取随机指定区间的随机数 * @param min (指定最小数) * @param max (指定最大数) * @return */private static int getRandomNum(int min,int max) { return RandomUtils.nextInt(min, max);} /** * 获得字体 * @return */ private static Font getFont() { return new Font("Fixedsys", Font.CENTER_BASELINE, 25); //名称、样式、磅值 } /** * 获得颜色 * @param fc * @param bc * @return */ private static Color getRandColor(int frontColor, int backColor) { if(frontColor > 255) frontColor = 255; if(backColor > 255) backColor = 255; int red = frontColor + random.nextInt(backColor - frontColor - 16); int green = frontColor + random.nextInt(backColor - frontColor -14); int blue = frontColor + random.nextInt(backColor - frontColor -18); return new Color(red, green, blue); } /** * 绘制字符串,返回绘制的字符串 * @param g * @param randomString * @param i * @return */ private static String drawString(Graphics g, String randomString, int i) { Graphics2D g2d = (Graphics2D) g;g2d.setFont(getFont()); //设置字体 g2d.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()));//设置颜色 String randChar = String.valueOf(getRandomChar(random.nextInt(randString.length()))); randomString += randChar; //组装 int rot = getRandomNum(5,10);g2d.translate(random.nextInt(3), random.nextInt(3)); g2d.rotate(rot * Math.PI / 180);g2d.drawString(randChar, 13*i, 20); g2d.rotate(-rot * Math.PI / 180);return randomString; } /** * 绘制干扰线 * @param g */ private static void drawLine(Graphics g) { //起点(x,y) 偏移量x1、y1 int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(13); int yl = random.nextInt(15); g.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()));g.drawLine(x, y, x + xl, y + yl); } /*** * @MethodName: getRandomCode* @Description: 生成Base64图片验证码* @param key* @return String 返回base64*/public static Validate getRandomCode() { validate = validate==null?new Validate():validate;// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics();// 获得BufferedImage对象的Graphics对象 g.fillRect(0, 0, width, height);//填充矩形 g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//设置字体 g.setColor(getRandColor(110, 133));//设置颜色 //绘制干扰线 for(int i = 0; i <= lineSize; i++) { drawLine(g); } //绘制字符 String randomString = ""; for(int i = 1; i <= StringNum; i++) { randomString = drawString(g, randomString, i); validate.setValue(randomString);} g.dispose();//释放绘图资源 ByteArrayOutputStream bs = null;try { bs = new ByteArrayOutputStream();ImageIO.write(image, "png", bs);//将绘制得图片输出到流 String imgsrc = Base64.byteArrayToBase64(bs.toByteArray());validate.setBase64Str(imgsrc);} catch (Exception e) { e.printStackTrace(); } finally { try {bs.close();} catch (IOException e) {e.printStackTrace();}finally{bs = null;}} return validate;} public static class Validate implements Serializable{private static final long serialVersionUID = 1L;private String Base64Str; //Base64 值private String base64Header = "data:image/png;base64,";//base64的头部信息private String value; //验证码值public String getBase64Str() {return Base64Str;}public void setBase64Str(String base64Str) {Base64Str = base64Str;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getBase64Header() {return base64Header;}public void setBase64Header(String base64Header) {this.base64Header = base64Header;}}}
三、校验openid
在之前所讲的第一点中,已做了openid的获取和保存,使用的话就是在确认投票的接口中进行判断是否是数据库中的有效openid即可,如果在数据库中查询不到,那么这个请求肯定是刷票的人搞的。
一个微信投票小程序防止刷票的想法相关推荐
- 零基础做一个微信答题小程序(四)
嗨!大家好,我是小蚂蚁.这一节里,我们继续分享如何在答完题后进行答案的比对,以及如何实现一个回顾功能. 在上一节里我们提到过,为了记录玩家的答题数据,我们创建了一个新的表格--玩家答题选项表,里面记录 ...
- 【征集+投票】微信投票小程序,公众号投票,免费创建投票打分平台,免费微信投票平台、微信投票小程序、微信群投票
作为公司.自媒体.学校等都经常会组织一些活动,需要先收集或者征集大家的作品,然后进行投票来提升活动氛围.通过微信投票获得结果,亦或者通过投票来引流增粉形成传播. 而传统的方式,通过邮 ...
- 微信投票小程序系统设计与实现
项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信小程序评选投票系统,前台用户使用小程序,后台管理使用基PHP+MySql的B/S架构:通过后台添加资讯.管理上传投票信息.用户管理等:用 ...
- 零基础做一个微信答题小程序(二)
嗨!大家好,我是小蚂蚁.在上一节里,我们了解了如何设计答题小程序中的题库--表格,并且知道了如何从题库中随机抽取指定数量的不重复的题目编号.这一节,我们将分享一下如何利用这些题目编号,获取到指定的题目 ...
- 零基础做一个微信答题小程序(三)
嗨!大家好,我是小蚂蚁.今天我们来分享一下如何实现答题功能,包含单选题和多选题的答题,以及如何记录玩家的答题数据. 单选题答题处理 对于单选题来讲,每个选项之间是互斥的,也就是说用户只能从 ABCD ...
- 图片投票小程序微信投票软件发起投票软件互动酷投票
现在来说,公司.企业.学校更多的想借助短视频推广自己. 通过微信投票小程序,网友们就可以通过手机拍视频上传视频参加活动,而短视频微信投票评选活动既可以给用户发挥的空间激发参与的热情,又可以让商家和企业 ...
- 随机投票小程序投票软件微信小程序微信小程序群投票投票评分小程序
近些年来,第三方的微信投票制作平台如雨后春笋般络绎不绝.随着手机的互联网的发展及微信开放平台各项基于手机能力的开放,更多人选择微信投票小程序平台,因为它有非常大的优势. 1.它比起微信公众号自带的投票 ...
- 投票小程序制作开发有哪些步骤?投票小程序开发有哪些功能?
线下计票的麻烦程度常常难倒活动举办方和需要计票的人,投票小程序的应用场景越来越多,功能更完备的投票小程序仍有市场前景. 微信投票小程序制作开发的步骤如下: 一.创建小程序账号 搜索微信公众号平台,注册 ...
- 活动星投票唱响泉城网络评选投票在线投票小程序如何挑选投票平台
现在来说,公司.企业.学校更多的想借助短视频推广自己. 通过微信投票小程序,网友们就可以通过手机拍视频上传视频参加活动,而短视频微信投票评选活动既可以给用户发挥的空间激发参与的热情,又可以让商家和企业 ...
- node.js毕业设计微信签到小程序(源码+程序+LW+部署)
该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程.欢迎交流 项目运行 环境配置: Node.js+ Vscode + Mysql5.7 + HBuilderX+Navicat11+Vue ...
最新文章
- 微信小程序 canvas 文字自动换行
- 试水区块链出版?纽约时报在招人了
- Oracle表空间查询及扩充表空间
- 关于网站根目录下面robots.txt文件的作用
- koa --- 使用Sequelize连接mysql
- Python错误,pip安装包或更新时因超时而报错误
- Nginx的五大应用场景详解
- 配置ssd为缓存_SSD小讲堂丨新电脑剪视频还卡?原因给你们找到了!
- Django1.6 运行manage.py 报错解决办法(ImportError)
- 关于二叉树前中后序遍历的常见问题
- java遍历对象的属性_Java遍历对象所有属性
- imagecopyresampled要生成彩色却生成了灰色图片
- 花两年时间去面试一个人——给准备面试的启发
- 英语六级 Java_过英语六级算什么,你过了Java25级了吗!
- 博弈论(van♂游戏) 笔记
- 红皮书——红色启示录
- 第8节 Kali及其他Linux系统软件分类及安装
- tomcat查看项目访问端口
- vgg19.npy下载
- 万众期待的AMD 7nm来了!将给数据中心带来“恐怖”性能,令人侧目!