如何做网站卖产品,做网站职业咋样,自动点击关键词软件,wordpress 商品表单目录
一、验证码的生成与校验
1. 创建生成验证码的工具类
2. 写一个 Controller
3. 实现验证码验证
1. 获取验证码
2. 验证码请求过程
3. 验证码的校验
4. 原理说明
5. 验证 6. 总结
二、JWT登录鉴权
1. 为什么要做登录鉴权#xff1f;
2. 什么是 JWT
3. JWT相比…目录
一、验证码的生成与校验
1. 创建生成验证码的工具类
2. 写一个 Controller
3. 实现验证码验证
1. 获取验证码
2. 验证码请求过程
3. 验证码的校验
4. 原理说明
5. 验证 6. 总结
二、JWT登录鉴权
1. 为什么要做登录鉴权
2. 什么是 JWT
3. JWT相比传统的鉴权方式的优点
1. Session 认证
2. Session 认证的缺点
3. JWT 的优点
4. 创建 JWT
1. 引入依赖
2. 创建JWT 工具类
3. 生成一个token
5. 使用 JWT
1. Vue 导入依赖
2. 前端创建 Cookie 工具类
3. 在登录组件设置 token
4. 判断是否有 token
5. 发送 token
6. 服务器获取token 在登录页面加入图形验证码
一、验证码的生成与校验
1. 创建生成验证码的工具类
package com.Util;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;public class ImageCodeUtils {/*** 图片的宽度*/private int width 160;/*** 图片的高度*/private int height 40;/*** 验证码字符个数*/private int codeCount 4;/*** 验证码干扰线数*/private int lineCount 20;/*** 验证码*/private String code null;private BufferedImage buffImg null;Random random new Random();public ImageCodeUtils() {createImage();}public ImageCodeUtils(int width, int height) {this.width width;this.height height;createImage();}public ImageCodeUtils(int width, int height, int codeCount) {this.width width;this.height height;this.codeCount codeCount;createImage();}public ImageCodeUtils(int width, int height, int codeCount, int lineCount) {this.width width;this.height height;this.codeCount codeCount;this.lineCount lineCount;createImage();}/*** 生成图片*/private void createImage() {// 字体的宽度int fontWidth width / codeCount;// 字体的高度int fontHeight height - 5;int codeY height - 8;// 图像bufferbuffImg new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g buffImg.getGraphics();// 设置背景色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));// a为要画出来的东西x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处g.drawString(strRand, i*fontWidth3, codeY);}}/*** 得到随机字符串* param n* return*/private String randomStr(int n) {String str1 ABCDEFGHJKMNOPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz1234567890;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;}/*** 得到随机颜色* param fc* param bc* return*/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)];}/*** 扭曲方法* param g* param w1* param h1* param color*/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;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();}
} 2. 写一个 Controller
方法前端访问调用一下工具类生成验证码图片并返回
引入一下依赖 dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion4.0.1/version/dependency 3. 实现验证码验证
1. 获取验证码 已经获取到验证码了那么下一步怎么验证验证码呢 2. 验证码请求过程 游览器那么多服务器怎么知道是哪个游览器请求的
这就可以使用到 Cookie 和 Session 3. 验证码的校验
把字符串形式的验证码存到 Session 从Session 中获取验证码 4. 原理说明 5. 验证 提示验证码错误
先查看验证验证码的SessionID是否和获取验证码的SessionID 一样 可以看到两个是不同的SessionID 服务器根据ID去获取的值是不同的所以验证码错误 那么为什么是不同的呢
这是因为 Vue 开启了代理转发所以每次请求的 Cookie中JSESSIONID 值会发生变化 如何解决呢
官方的解决方案是代理转发的 请求 URL 前缀和服务器请求路径的项目名相同就没问题了 原来的请求路径 修改后的请求路径
注意vue 的配置文件修改后需要重启 修改服务器的 URL 修改后重启服务器 可以看到SessionID值是一样的了 验证成功 6. 总结
会话开始当一个用户首次访问一个网站服务器会创建一个新的HttpSession对象并生成一个唯一的会话ID通常称为JSESSIONID。会话ID存储在Cookie中服务器会在响应中包含一个Set-Cookie头将这个会话ID作为cookie的一部分发送给浏览器。浏览器会存储这个cookie。后续请求当用户继续与网站交互时浏览器会自动在每个后续请求中包含这个会话ID的cookie。这使得服务器能够识别出请求来自于哪个具体的会话。服务器识别会话服务器接收到请求后会读取请求头中的cookie提取出会话ID然后使用这个ID在服务器端的会话存储中查找相应的HttpSession对象。会话数据访问一旦找到了HttpSession对象服务器就可以从这个对象中读取或写入数据比如用户信息、登录状态等。会话结束当用户关闭浏览器或会话超时HttpSession对象会被销毁除非服务器端有特别的配置来延长会话的存活时间。 二、JWT登录鉴权
JWT 全程 JSON Web Token
1. 为什么要做登录鉴权
安全考虑需要登录之后有操作权限了之后才能访问API接口 2. 什么是 JWT
JWTJSON Web Token是一种在网络应用中用于身份验证和授权的令牌。你可以把它想象成一张电子版的“身份证”或“通行证”。
当你登录一个网站后服务器会生成一个JWTJWT 本质就是一条字符串它把你的身份信息比如用户名保存到一个JSON字符串中然后进行编码得到一个token 令牌然后把这个令牌发回给你的浏览器。之后每当你的浏览器想要访问受保护的资源时它都会带上这个JWT。 3. JWT相比传统的鉴权方式的优点
1. Session 认证 我们知道 HTTP 是一种无状态的协议HTTP协议在设计上不保留任何两次请求之间的信息。换句话说当你向一个网站发送请求时比如浏览一个网页这个请求是独立的它并不依赖于你之前对该网站做的任何事情。一旦服务器处理完你的请求并返回了响应它就会忘记这次交互就像从来没有发生过一样。 所以为了让服务器知道是谁在访问我们会在游览器第一次登陆成功的时候创建一个SessionID然后把用户信息保存在 Session 对象中最后把SessionID放到 Cookie 返回给游览器这样下次游览器再访问的时候就知道是谁了这就是基于Session 认证的过程
2. Session 认证的缺点
由于基于Cookie而cookie无法跨域所以session的认证也无法跨域
Session 是保存在服务器的会使服务器的开销增大 3. JWT 的优点
简洁
无状态存储以加密的形式保存在客户端
时效性可以设置多少时间失效 4. 创建 JWT
1. 引入依赖 dependencygroupIdio.github.qyg2297248353.components/groupIdartifactIdjsonwebtoken-jjwt/artifactIdversion2.0.0/version/dependency 2. 创建JWT 工具类
package com.Util;import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Map;
public class JwtUtil {// 私钥private static String privateKey 12345678901234567890123456789012abcdefghijklmn;/** 生成token* param claims 要加密的数据* return* */public static String generateToken(MapString, Object claims) {// 使用JWT构建器构建令牌// 添加负载claims存储用户信息// 使用HS256算法和私钥进行签名确保令牌的完整性和安全性// 最后将令牌以JSON格式编码并压缩为紧凑字符串格式String token Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, privateKey) // HS256加密密钥长度必须大于等于256 bit.compact();return token;}
}3. 生成一个token
在 Service 层调JWT工具类生成 token 登录成功后返回的 token 那么如何在每次请求都带上这个 token 呢
可以把token 放到 Cookie 里
5. 使用 JWT
1. Vue 导入依赖
npm i js-cookie2.2.0 -S
2. 前端创建 Cookie 工具类 3. 在登录组件设置 token
引入token 工具类的方法 4. 判断是否有 token
在路由器文件的路由守卫中判断如果有 token 则放行 验证 5. 发送 token
在自定义 axios 文件的请求拦截器中添加 token 自定义 axios 可以看到在登录成功后请求头里有 token 6. 服务器验证token
服务器在哪个 Controller 里判断在所有 Controller 都判断一下比较麻烦
这就可以使用拦截器在拦截器中统一判断
1. 创建登录拦截器 2. 配置拦截器
在spring 配置文件配置拦截器 !--配置拦截器--mvc:interceptorsmvc:interceptormvc:mapping path/**/ !--拦截所有请求--mvc:exclude-mapping path/Admin/Login/ !--放行登录操作--mvc:exclude-mapping path/ImageCode/Captcha/ !--放行请求验证码--bean classcom.Interceptor.LoginInterceptor//mvc:interceptor/mvc:interceptors 这样就可以在每次请求资源时都带有token服务器根据 token 判断是否有权限访问数据
目前在 Vue 的路由守卫有判断是否登录token以及在服务器的拦截器也有判断