范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

SpringBootVue项目中实现登录验证码校验

  在各大项目中,为保证数据的安全性,通常在登录页面加入验证码校验,以防止爬虫带来的数据泄露危机。本文将介绍在前后端分离的项目中,怎样实现图形验证码校验。 实现思路
  第一步:在后端创建一个生成随机验证码的工具类和接收请求验证码的接口。工具类的主要作用生成随机验证码和对应的图片。接口的作用是将生成的随机验证码保存到session,同时,将图片进行base64编码,然后返回给前端。
  第二步:在登录页面创建的同时获取验证码,并将后端传回来得key和编码后的字符串拼接,绑定img标签的src属性。此外,当用户点击验证码的img标签时,重新获取验证码,后端session更新验证码。
  第三步:后端登录接口接收登录请求时,将用户提交的验证码和session中的验证码进行比对,不相同则返回相应信息给前端进行提示,相同则进行账号密码的匹配。 测试案例创建验证码生成的工具类 package com.check.utils; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random;  import javax.imageio.ImageIO;  public class CreateImageCode {     // 图片的宽度。     private int width = 160;     // 图片的高度。     private int height = 40;     // 验证码字符个数     private int codeCount = 4;     // 验证码干扰线数     private int lineCount = 20;     // 验证码     private String code = null;     // 验证码图片Buffer     private BufferedImage buffImg = null;     Random random = new Random();      public CreateImageCode() {         creatImage();     }      public CreateImageCode(int width, int height) {         this.width = width;         this.height = height;         creatImage();     }      public CreateImageCode(int width, int height, int codeCount) {         this.width = width;         this.height = height;         this.codeCount = codeCount;         creatImage();     }      public CreateImageCode(int width, int height, int codeCount, int lineCount) {         this.width = width;         this.height = height;         this.codeCount = codeCount;         this.lineCount = lineCount;         creatImage();     }      // 生成图片     private void creatImage() {         int fontWidth = width / codeCount;// 字体的宽度         int fontHeight = height - 5;// 字体的高度         int codeY = height - 8;          // 图像buffer         buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);         Graphics g = buffImg.getGraphics();         //Graphics2D g = buffImg.createGraphics();         // 设置背景色         g.setColor(getRandColor(200, 250));         g.fillRect(0, 0, width, height);          // 设置字体         //Font font1 = getFont(fontHeight);         Font font = new Font("Fixedsys", Font.BOLD, fontHeight);         g.setFont(font);          // 设置干扰线         for (int i = 0; i < lineCount; i++) {             int xs = random.nextInt(width);             int ys = random.nextInt(height);             int xe = xs + random.nextInt(width);             int ye = ys + random.nextInt(height);             g.setColor(getRandColor(1, 255));             g.drawLine(xs, ys, xe, ye);         }          // 添加噪点         float yawpRate = 0.01f;// 噪声率         int area = (int) (yawpRate * width * height);         for (int i = 0; i < area; i++) {             int x = random.nextInt(width);             int y = random.nextInt(height);              buffImg.setRGB(x, y, random.nextInt(255));         }         String str1 = randomStr(codeCount);// 得到随机字符         this.code = str1;         for (int i = 0; i < codeCount; i++) {             String strRand = str1.substring(i, i + 1);             g.setColor(getRandColor(1, 255));             // g.drawString(a,x,y);             // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处             g.drawString(strRand, i*fontWidth+3, codeY);         }     }      // 得到随机字符     private String randomStr(int n) {         String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";         String str2 = "";         int len = str1.length() - 1;         double r;         for (int i = 0; i < n; i++) {             r = (Math.random()) * len;             str2 = str2 + str1.charAt((int) r);         }         return str2;     }      // 得到随机颜色     private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色         if (fc > 255)             fc = 255;         if (bc > 255)             bc = 255;         int r = fc + random.nextInt(bc - fc);         int g = fc + random.nextInt(bc - fc);         int b = fc + random.nextInt(bc - fc);         return new Color(r, g, b);     }      /**      * 产生随机字体      */     private Font getFont(int size) {         Random random = new Random();         Font font[] = new Font[5];         font[0] = new Font("Ravie", Font.PLAIN, size);         font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);         font[2] = new Font("Fixedsys", Font.PLAIN, size);         font[3] = new Font("Wide Latin", Font.PLAIN, size);         font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);         return font[random.nextInt(5)];     }      // 扭曲方法     private void shear(Graphics g, int w1, int h1, Color color) {         shearX(g, w1, h1, color);         shearY(g, w1, h1, color);     }      private void shearX(Graphics g, int w1, int h1, Color color) {         int period = random.nextInt(2);         boolean borderGap = true;         int frames = 1;         int phase = random.nextInt(2);         for (int i = 0; i < h1; i++) {             double d = (double) (period >> 1)                     * Math.sin((double) i / (double) period                     + (6.2831853071795862D * (double) phase)                     / (double) frames);             g.copyArea(0, i, w1, 1, (int) d, 0);             if (borderGap) {                 g.setColor(color);                 g.drawLine((int) d, i, 0, i);                 g.drawLine((int) d + w1, i, w1, i);             }         }     }     private void shearY(Graphics g, int w1, int h1, Color color) {         int period = random.nextInt(40) + 10; // 50;         boolean borderGap = true;         int frames = 20;         int phase = 7;         for (int i = 0; i < w1; i++) {             double d = (double) (period >> 1)                     * Math.sin((double) i / (double) period                     + (6.2831853071795862D * (double) phase)                     / (double) frames);             g.copyArea(i, 0, 1, h1, 0, (int) d);             if (borderGap) {                 g.setColor(color);                 g.drawLine(i, (int) d, i, 0);                 g.drawLine(i, (int) d + h1, i, h1);             }         }     }     public void write(OutputStream sos) throws IOException {         ImageIO.write(buffImg, "png", sos);         sos.close();     }      public BufferedImage getBuffImg() {         return buffImg;     }      public String getCode() {         return code.toLowerCase();     }  } 编写获取验证码的接口  @RequestMapping("/login") @RestController public class LoginController {     @GetMapping("/getImage")     public Result getImage(HttpServletRequest request) throws IOException {         Map result = new HashMap<>();         CreateImageCode createImageCode = new CreateImageCode();         //获取验证码         String securityCode = createImageCode.getCode();         //验证码存入session         String key = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());         request.getServletContext().setAttribute(key, securityCode);         //生成图片         BufferedImage image = createImageCode.getBuffImg();         //进行base64编码         ByteArrayOutputStream bos = new ByteArrayOutputStream();         ImageIO.write(image, "png", bos);         String string = Base64Utils.encodeToString(bos.toByteArray());         result.put("key", key);         result.put("image", string);         return ResultUtils.success("请求成功",result);     } } 编写axios请求验证码的函数  import requests from "./request"; export const GetImage=()=>requests({     url: "/login/getImage",     method: "get" })vuex中编写异步方法  import {GetImage} from "../api/login" const state={}; const mutations={}; const actions={     async getImage(){         let result=await GetImage().then();         return result.dataset;     } }; const getters={}; export default{     state,     mutations,     actions,     getters }将验证码绑定给img的src  async getimage() {       let result = await this.$store.dispatch("getImage");       this.imageurl = "data:image/png;base64," + result.image;       this.adminInfo.key = result.key;  },编写登录接口  @PostMapping("/login")     public Result login(@RequestBody Login login, HttpServletRequest request){         System.out.println(login);         String keyCode = (String) 		request.getServletContext().getAttribute(login.getKey());         if(keyCode.equals(login.getCode().toLowerCase())){             Admin admin = new Admin();             admin.setUsername(login.getUsername());             admin.setPassword(login.getPassword());             Admin admin1 = adminService.login(admin);             if(admin1!=null){                return ResultUtils.success("登录成功",admin1);             }else {                 return ResultUtils.error("账号或密码错误!");             }         }else {             return ResultUtils.error("验证码错误!");         }测试结果前端页面
  输入错误验证码

脾胃不好,该吃啥?脾胃的健康对人体至关重要,是人体化生气血的重要器官,但是受到饮食情绪自身体质等的因素影响,当代上班一族的脾胃很容易出现问题。如果长期脾胃失调,还会影响到其他脏器的正常工作。脾胃不好TA记者凯尔特人仍在寻找机会使用1710万美元的交易特例直播吧7月10日讯据TA记者JaredWeiss报道,凯尔特人仍在寻找机会使用1710万美元的交易特例。消息人士透露,考虑到阵容的深度和奢侈税的情况,绿军很可能将这个交易特例用来作年度爽剧!疯批恶女,满嘴谎话,却玩转上流社会她,是一个白富美。父母在美国做生意,家境殷实。容貌出众,擅长绘画,气质脱俗。她是人群中无法忽视的存在,总是很受同学欢迎。考上名牌大学后,她又有一个品学兼优的男友,即将一起出国留学。三伏天将至,饮食有讲究,建议喝2粥吃2菜,补充营养,安稳度夏天小暑已经过去,即将开始今年的三伏天,温度升高,身心烦躁,都想一下子跨越到凉爽的冬天。夏天高温湿热,很容易使人生病,尤其是很多人不重视饮食,经常吃一些对身体有害的食物。其实我们每天都吃饱饭后昏昏欲睡,为什么午饭过后人就开始犯困?科幻网7月10日讯(刘亚珠)人们在吃完午饭后便开始出现饭后困倦工作倦怠精神萎靡等情况,很多人认为这是大脑缺氧所发出的信号。午后饭困属于一种正常的生理现象,人在饭后容易疲乏易倦,十分季羡林一生多病痛,却能长寿活到98岁,全靠三不养生术养生风气,自古就有,甚至于成为古今中外的主流话题。对于养生,最有心得的当属中国,因为三皇五帝到如今,养生几乎成为一种主流意识,尤其是在国粹医学的加持下,华夏的养生术更是五花八门,门提醒!这样的西红柿不能吃西红柿营养价值丰富,吃西红柿有很多好处。尤其夏天的时候,不少人喜欢生吃西红柿。可近期,网络上却有一种说法有些西红柿不能吃,会引起恶心呕吐等中毒症状,甚至可能会引起死亡,还说西红柿熟比米色优雅,比棕色显白,今夏的裸肤色凭什么火了?文洛薇Hi,我是洛薇,继续我们的时尚穿搭之旅,变美永远不迷路。小暑过后,热气开始翻腾。炽热与葱茏相互辉映,交织出一个层次分明饱满热情的火辣景象。天蓝云白水清地绿,立体缠绕,一片喧闹国乒主力抵达欧洲!马龙带王楚钦一起训练,女队4人共用一张球台国乒主力抵达欧洲!马龙带王楚钦一起训练,女队4人共用一张球台。国乒主力已经安全抵达匈牙利布达佩斯了,为即将开打的WTT球星挑战赛进行备战,未来一段时间国际乒联将在欧洲举办多站WTT曝德容拒绝加盟曼联原因听老婆的话不去被诅咒的队还有其他8点巴萨球星弗兰基德容对于转会曼联的态度非常明确不去,即使两家俱乐部谈妥转会费,自己也不愿意加盟曼联。德容将在当地时间本周末归队,下周一进行季前体检,决心要为哈维执教的巴萨继续效力。在1年1750万!湖人组超级双塔?这要重回NBA顶级的节奏就欧文交易和篮网管理层扯皮之际,湖人管理层也没闲着,接连签下达米安琼斯和托马斯布莱恩特两位中锋。一下来俩中锋,终于不用像刚刚结束的赛季那样,詹姆斯安东尼这样的锋线球员顶上五号位了。
过上理想生活,可以从这5件小事做起知乎上有个话题你讨厌现在的生活吗?讨厌的不是现在的生活,是现在以这个样子生活的自己。这个答案引起了很多人的共鸣。虽然,很多人讨厌现在的自己,但更糟糕的是他们不知道如何去改变,只能放对话A股成长力丨晶瑞电材总经理薛利新半导体与新能源业务何以协同并进?21世纪经济报道记者张赛男上海报道近两年的A股市场,半导体和新能源称得上是两大最火的赛道,苏州的一家电子材料公司晶瑞电材(300655。SZ)则同时布局了这两大赛道。晶瑞电材起源于深圳社保一档二档三档的区别,非深户缴纳几档最好?深圳一二三档社保区别较大,对此真社宝专门写过深圳社保一二三档区别,门诊住院能报销多少?有兴趣可以认真对一下。相对来说社保分为一二三档是深圳的一种特色。其主要的差异在于医保,养老保险vivoT2x昨天正式发布,对比RedmiNote11TPro配置有啥区别一眼看懂机型对比RedmiNote11TProvivoT2x性能参数天玑8100LPDDR5UFS3。1天玑1300LPDDR4XUFS3。1屏幕参数6。6英寸144Hz华星光电天马LCD宝宝一岁后以辅食为主,还是以奶粉为主呢?看了本文你就明白了宝宝一岁后是以辅食为主,还是以奶粉为主呢?宝妈小文带着快两岁的宝宝去做儿保,被医生指出了一直以来所犯的一个很严重的问题。医生检查宝宝后,对小文说孩子有点贫血,身体发育也是中等偏下,有人让日本文豪看呆,有人拿下木村拓哉,美到令人窒息的昭和美人如今网络上和演艺圈的美女遍地开花,乍看都很漂亮,但遗憾的是魅力不足,独一无二的美更是少之又少。然而,出生于上世纪1926至1989年,被称作昭和美人的日本女演们,有的典雅美,有的纯用乐高还原美景乐高创意项目希腊圣托里尼分享圣托里尼(Santorini),我们总能从各种渠道听见或看到这个名字公众号的推荐里博主们的视频里蜜月友人的朋友圈里感觉没印象?不要紧,让照片打开记忆。如梦似幻不是吗?新月状的圣托里瞭望专访全国人大常委会委员中国社会保障学会会长郑功成全国人大常委会委员中国社会保障学会会长郑功成灵活就业或打零工正在成为当今世界就业市场的新主流方式,而中国则更以规模大速度快就业方式多样化而处于领跑位置有效保障规模庞大的灵活就业人员今日油价调整信息5月29日调整后,全国9295汽油价格最新售价表今日最新油价调整今天是5月29日,星期日。油价大涨又要来了,5月油价两连涨!在本月中旬油价调整上涨后,随着时间的推进,5月份第2轮油价调整的十个工作日统计周期已经进行90时间的统计挑战登高极限,恐高症绝对要远离的恐怖景点你想知道自己有没有恐高症吗?请尝试挑战以下这些景点,如果能游览以下任何两处景点,恭喜你超越了91的现代都市人,成功克服了恐高症!秘鲁印加阶梯秘鲁的印加阶梯,它修建在马丘比丘古城之中徒步耿井湿地公园这个周末我们来到了耿井湿地公园,它紧邻耿井水库西面,结合周边自然生态与水势地势的自然条件,打造了城市生态人文景观相融合的湿地公园。不少附近的居民有的在湖边漫步骑行,有的在林间小坐,