angular前端生成验证码(ts组件)
账号登录的时候,添加校验验证码功能可以防止暴力破解密码,增加破解成本,此为前端生成验证码的方法,主要是将随机验证码,随机颜色,随机线条,随机点,再加上随机偏转等生成一个canvas,大家按需取用。
先看效果:
一、HTML
在html中需添加#标签,标签名自定
<div class="login-picture" id="loginMaskLi">
<canvas class="picture-canvas" #verifyCode type="text"
(click)="doInitVerifyCode($event)" disabled="disabled"></canvas>
</div>
二、css
设置需要的长宽样式
.login-picture {
width: 140px;
height: 48px;
.picture-canvas {
width: 100%;
// height: 100%;
}
}
三、ts
import {
Component,
ElementRef,
OnInit,
Output,
ViewChild,
EventEmitter,
} from '@angular/core';
//生成验证图片
@Component({
selector: 'app-login-picture',
templateUrl: './login-picture.component.html',
styleUrls: ['./login-picture.component.scss'],
})
export class LoginPictureComponent implements OnInit {
@ViewChild('verifyCode', { static: true })
verifyCode!: ElementRef;
@Output() private outer = new EventEmitter();
constructor() {}
// public showAuthCode: string;
public verifyCodeLine: number = 8;//线条数
public verifyCodeNum: number = 4;//验证码字符长度
public verifyCodeWidth: any = 140;//验证码宽度
public verifyCodeHeight: any = 48;//验证码高度
ngOnInit(): void {}
// 随机生成验证码
//生成随机整数
randomNum(min: any, max: any) {
return parseInt(Math.random() * (max - min + 1) + min);
}
//生成随机颜色
randomCol(min: any, max: any) {
const r = this.randomNum(min, max);
const g = this.randomNum(min, max);
const b = this.randomNum(min, max);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
//生成验证码(纯字符串)
randomStr() {
let codeStr: string = '';
const codeArr: any[] = [];
const randomArray=[0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R', 'S','T','U','V','W','X','Y','Z'];
const verifyCodePic = this.verifyCode.nativeElement.getContext('2d');
for (let i = 0; i < this.verifyCodeNum; i++) {
const verifyChar = randomArray[this.randomNum(0, randomArray.length - 1)];
const fontSize = this.randomNum(25, 35);
const angle = this.randomNum(-30, 30);
verifyCodePic.font = fontSize + 'px consolas';
verifyCodePic.textBaseline = 'top';
verifyCodePic.save();
verifyCodePic.fillStyle = this.randomCol(50, 150);
verifyCodePic.translate(30 * i + 15, 15);
verifyCodePic.rotate((angle * Math.PI) / 180);
verifyCodePic.fillText(verifyChar, -10, -5);
verifyCodePic.restore();
codeArr.push(verifyChar);
}
//将验证码抛出给父组件
codeStr = codeArr.join('');
this.outer.emit(codeStr);
}
//随机线条
randomLine() {
const verifyCodePic = this.verifyCode.nativeElement.getContext('2d');
for (let i = 0; i < this.verifyCodeLine; i++) {
verifyCodePic.beginPath();
verifyCodePic.moveTo(
this.randomNum(0, this.verifyCodeWidth),
this.randomNum(0, this.verifyCodeHeight)
);
verifyCodePic.lineTo(
this.randomNum(0, this.verifyCodeWidth),
this.randomNum(0, this.verifyCodeHeight)
);
verifyCodePic.strokeStyle = this.randomCol(50, 230);
verifyCodePic.closePath();
verifyCodePic.stroke();
}
}
//随机噪点
randomDot() {
const verifyCodePic = this.verifyCode.nativeElement.getContext('2d');
const verifyCodeDot = 100;
for (let i = 0; i < verifyCodeDot; i++) {
verifyCodePic.beginPath();
verifyCodePic.arc(
this.randomNum(0, this.verifyCodeWidth),
this.randomNum(0, this.verifyCodeHeight),
1,
0,
2 * Math.PI
);
verifyCodePic.closePath();
verifyCodePic.fillStyle = this.randomCol(50, 200);
verifyCodePic.fill();
}
}
//初始化验证码
initVerifyCode() {
const verifyCodePic = this.verifyCode.nativeElement.getContext('2d');
this.verifyCode.nativeElement.setAttribute('width', this.verifyCodeWidth);
this.verifyCode.nativeElement.setAttribute('height', this.verifyCodeHeight);
verifyCodePic.fillStyle = this.randomCol(180, 255);
verifyCodePic.fillRect(0, 0, this.verifyCodeWidth, this.verifyCodeHeight);
this.randomStr();
this.randomLine();
this.randomDot();
}
}
四、使用
使用就用正常的angular组件使用方式就行,可以添加#标签来调用initVerifyCode()方法实现验证码刷新。
五、优缺点及解决建议
1.优点是前端直接生成验证码不需要后台参与,不用调用接口。
2.缺点是过不了渗透测试,可以跳过前端界面直接使用postman等接口调试工具直接访问接口暴力破解密码。
3.建议还是后台生成随机字符串验证码,前端拿到验证码生成验证码canvas,然后登录时前端后台共同校验。