Récemment, j'ai reçu une tâche au travail pour développer une fonction de code de vérification de page. J'ai consulté des informations en ligne et, combinées à mes connaissances antérieures en dessin, j'ai mis en œuvre la solution suivante. Le code de vérification généré ressemble à ceci :
Problèmes à résoudre :
1. Comment générer des images de manière aléatoire
pour générer des objets System.Drawing.Bitmap et utiliser System.Drawing.Graphics pour dessiner dans les objets bitmap.
2. Comment transmettre les données d'image via les paramètres de la méthode WebService
pour générer l'objet Bitmap dans un flux d'octets, et WebMothod utilise un tableau d'octets pour renvoyer le flux d'octets.
Exemple :
1. Utilisez VS.NET 2003 pour créer un projet de service Web ASP.NET. Le nom du service par défaut est MyService et une WebMethod nommée GenerateVerifyImage est ajoutée à MyService. Le code de cette méthode est le suivant :
/// <summary>
/// Générer un code de vérification d'image
/// </summary>
/// <param name="nLen">La longueur du code de vérification</param>
/// <param name="strKey">Paramètres de sortie, contenu du code de vérification</param>
/// <returns>Flux d'octets d'image</returns>
[MéthodeWeb]
public byte[] GenerateVerifyImage(int nLen,ref string strKey)
{
int nBmpWidth = 13*nLen+5;
int nBmpHauteur = 25 ;
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(nBmpWidth,nBmpHeight);
// 1. Générer une couleur d'arrière-plan aléatoire
int nRed,nGreen,nBlue; // La couleur ternaire du fond
System.Random rd = new Random((int)System.DateTime.Now.Ticks);
nRouge = rd.Suivant(255)%128+128 ;
nVert = rd.Suivant(255)%128+128 ;
nBlue = rd.Next(255)%128+128;
// 2. Remplir l'arrière-plan bitmap
Graphique System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp);
graph.FillRectangle (nouveau SolidBrush (System.Drawing.Color.FromArgb (nRed, nGreen, nBlue))
,0
,0
,nBmpLargeur
,nBmpHauteur);
// 3. Dessinez des lignes d'interférence en utilisant une couleur légèrement plus foncée que l'arrière-plan
int nLignes = 3;
Stylo System.Drawing.Pen = nouveau System.Drawing.Pen(System.Drawing.Color.FromArgb(nRed-17,nGreen-17,nBlue-17),2);
pour(int a =0;a< nLines;a++)
{
int x1 = rd.Next() % nBmpWidth;
int y1 = rd.Next() % nBmpHeight;
int x2 = rd.Next() % nBmpWidth;
int y2 = rd.Next() % nBmpHeight;
graph.DrawLine(stylo,x1,y1,x2,y2);
}
// Le jeu de caractères utilisé peut être étendu à tout moment et la probabilité d'apparition des caractères peut être contrôlée
string strCode = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 4. Boucle pour obtenir des caractères et les dessiner
chaîne strResult = "" ;
pour(int i=0;i<nLen;i++)
{
int x = (i*13 + rd.Next(3));
int y = rd.Next(4) + 1;
// Détermine la police
System.Drawing.Font font = new System.Drawing.Font("Courier Nouveau",
12 + rd.Suivant()%4,
System.Drawing.FontStyle.Bold);
char c = strCode[rd.Next(strCode.Length)]; // Récupère des caractères aléatoires
strResult += c.ToString();
// Dessine des caractères
graph.DrawString(c.ToString(),
fonte,
nouveau SolidBrush(System.Drawing.Color.FromArgb(nRed-60+y*3,nGreen-60+y*3,nBlue-40+y*3)),
x,
y);
}
// 5. Flux d'octets de sortie
System.IO.MemoryStream bstream = new System.IO.MemoryStream();
bmp.Save(bstream,System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
graph.Dispose();
strKey = strResult;
byte[] byteReturn = bstream.ToArray();
bstream.Close();
return byteReturn;
}
2. Testez la WebMethod, ajoutez un WebForm, référencez le WebService ci-dessus et le nom de référence est imagesvr. Ajoutez du code dans Page_Load :
...
imagesvr.MyService imgsvr = new imagesvr.MyService();
chaîne strKey = "" ;
byte[] data = imgsvr.GenerateVerifyImage(5,ref strKey);
Response.OutputStream.Write(data,0,data.Length);
...
3. Courez. Chaque fois que le formulaire Web est actualisé, un code de vérification d'image nouvellement généré sera affiché et le paramètre de sortie strKey de la fonction enregistre le contenu réel du code de vérification, qui peut être enregistré dans la session pour vérification.
Après avoir développé le code de vérification d'image la dernière fois, sur la base des suggestions de certains amis, sur la base du principe selon lequel le code de vérification est facile à reconnaître (pour les gens), difficile à déchiffrer et beau, l'algorithme de génération de code de vérification a été amélioré, et la méthode de filtrage d'image a été utilisée pour filtrer les images. Le code de vérification est soumis à des interférences anti-fissuration, et l'exemple d'image résultant est le suivant :
L'effet de filtre utilise principalement l'algorithme d'onde, qui produit un effet de superposition en traitant la forme d'onde sinusoïdale de l'axe X et de l'axe Y. La description principale de l'algorithme est la suivante :
private const double PI = 3.1415926535897932384626433832795 ;
private const double PI2 = 6.283185307179586476925286766559
/// <résumé>
/// Image déformée par onde sinusoïdale
/// </summary>
/// <param name="srcBmp"></param>
/// <param name="bXDir"></param>
/// <param name="nMultValue">Multiple d'amplitude de la forme d'onde</param>
/// <param name="dPhase">Phase de démarrage de la forme d'onde, plage de valeurs [0-2*PI)</param>
/// <retours></retours>
public System.Drawing.Bitmap TwistImage (Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
{
System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width,srcBmp.Height);
// Remplir l'arrière-plan du bitmap avec du blanc
Graphique System.Drawing.Graphics = System.Drawing.Graphics.FromImage(destBmp);
graph.FillRectangle(nouveau SolidBrush(System.Drawing.Color.White),0,0,destBmp.Width,destBmp.Height);
graph.Dispose();
double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;
for(int i=0;i<destBmp.Width;i++)
{
pour(int j=0;j<destBmp.Height;j++)
{
double dx = 0 ;
dx = bXDir ? (PI2*(double)j)/dBaseAxisLen : (PI2*(double)i)/dBaseAxisLen;
dx += dPhase ;
double dy = Math.Sin(dx);
// Récupère la couleur du point actuel
int nVieuxX = 0,nVieuxY = 0;
nOldX = bXDir i + (int)(dy*dMultValue) : i;
nOldY = bXDir ? j : j + (int)(dy*dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i,j);
if(nOldX >= 0 && nOldX < destBmp.Width
&& nOldY >=0 && nOldY < destBmp.Hauteur)
{
destBmp.SetPixel(nOldX,nOldY,color);
}
}
}
renvoie destBmp ;
}
L'image d'exemple au début est la superposition de deux effets de forme d'onde. Les deux effets concernent respectivement la direction de l'axe X et la direction de l'axe Y. Si vous annulez le remplissage de la couleur d'arrière-plan du bord, vous pouvez voir l'impact de. l'algorithme sur les graphiques, comme indiqué ci-dessous :
Le code de vérification ainsi généré ressemble beaucoup au code de vérification sur le site de Google. Bien entendu, si vous êtes intéressé, vous pouvez également ajouter d'autres effets de filtre, comme l'étirement, la rotation, la mosaïque, etc. Mais veuillez noter que plus le code de vérification du site Web est complexe, mieux c'est. Vous devez trouver un équilibre entre vitesse et sécurité.