Recentemente, recebi uma tarefa no trabalho para desenvolver uma função de código de verificação de página. Consultei algumas informações online e, combinadas com meu conhecimento anterior em desenho, implementei a seguinte solução. O código de verificação gerado é assim:
Problemas a serem resolvidos:
1. Como gerar imagens aleatoriamente
para gerar objetos System.Drawing.Bitmap e usar System.Drawing.Graphics para desenhar nos objetos bitmap.
2. Como passar dados de imagem por meio de parâmetros no método WebService
para gerar o objeto Bitmap em um fluxo de bytes, e o WebMothod usa uma matriz de bytes para retornar o fluxo de bytes.
Exemplo:
1. Use o VS.NET 2003 para criar um projeto de serviço da Web ASP.NET. O nome do serviço padrão é MyService e um WebMethod chamado GenerateVerifyImage é adicionado a MyService. O código deste método é o seguinte:
/// <summary>
/// Gera código de verificação de imagem
/// </sumário>
/// <param name="nLen">O comprimento do código de verificação</param>
/// <param name="strKey">Parâmetros de saída, conteúdo do código de verificação</param>
/// <returns>Fluxo de bytes de imagem</returns>
[WebMethod]
byte público[] GenerateVerifyImage(int nLen,ref string strKey)
{
int nBmpLargura = 13*nLen+5;
int nBmpAltura = 25;
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(nBmpWidth,nBmpHeight);
// 1. Gera cor de fundo aleatória;
int nRed,nGreen,nBlue; // A cor ternária do fundo
System.Random rd = new Random((int)System.DateTime.Now.Ticks);
nVermelho = rd.Próximo(255)%128+128;
nVerde = rd.Próximo(255)%128+128;
nBlue = rd.Next(255)%128+128;
// 2. Preencha o fundo do bitmap
Gráfico System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp);
gráfico.FillRectangle(novo SolidBrush(System.Drawing.Color.FromArgb(nRed,nGreen,nBlue))
,0
,0
,nBmpLargura
,nBmpAltura);
// 3. Desenhe linhas de interferência, usando uma cor um pouco mais escura que o fundo
int nLinhas = 3;
Caneta System.Drawing.Pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(nRed-17,nGreen-17,nBlue-17),2);
for(int a =0;a< nLinhas;a++)
{
int x1 = rd.Next()% nBmpWidth;
int y1 = rd.Next() % nBmpHeight;
int x2 = rd.Next()% nBmpWidth;
int y2 = rd.Next() % nBmpHeight;
gráfico.DrawLine(caneta,x1,y1,x2,y2);
}
// O conjunto de caracteres utilizado pode ser expandido a qualquer momento e a probabilidade de aparecimento de caracteres pode ser controlada
string strCode = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 4. Loop para obter caracteres e desenhá-los
string strResult = "";
for(int i=0;i<nLen;i++)
{
int x = (i*13 + rd.Próximo(3));
int y = rd.Next(4) + 1;
// Determina a fonte
Fonte System.Drawing.Font = new System.Drawing.Font("Courier Novo",
12 + rd.Próximo()%4,
System.Drawing.FontStyle.Bold);
char c = strCode[rd.Next(strCode.Length)] // Obtém caracteres aleatórios
strResult += c.ToString();
// Desenha caracteres
gráfico.DrawString(c.ToString(),
fonte,
novo SolidBrush(System.Drawing.Color.FromArgb(nRed-60+y*3,nGreen-60+y*3,nBlue-40+y*3)),
x,
e);
}
// 5. Fluxo de bytes de saída
System.IO.MemoryStream bstream = new System.IO.MemoryStream();
bmp.Save(bstream,System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
gráfico.Dispose()
;
byte[] byteReturn = bstream.ToArray();
bstream.Close();
return byteReturn;
}
2. Teste o WebMethod, adicione um WebForm, faça referência ao WebService acima e o nome de referência é imagesvr. Adicione o código em Page_Load:
...
imagensvr.MyService imgsvr = novas imagensvr.MyService();
stringstrKey = "";
byte[] dados = imgsvr.GenerateVerifyImage(5,ref strKey);
Response.OutputStream.Write(dados,0,dados.Length);
...
3. Corra. Cada vez que o WebForm for atualizado, um código de verificação de imagem recém-gerado será exibido e o parâmetro de saída strKey da função salva o conteúdo real do código de verificação, que pode ser salvo na Sessão para verificação.
Depois de desenvolver o código de verificação de imagem da última vez, com base nas sugestões de alguns amigos, com base no princípio de que o código de verificação é fácil de reconhecer (para as pessoas), difícil de decifrar e bonito, o algoritmo de geração do código de verificação foi aprimorado, e o método de filtro de imagem foi usado para filtrar as imagens. O código de verificação está sujeito a interferência anti-cracking e o exemplo de imagem resultante é o seguinte:
O efeito de filtro usa principalmente o algoritmo de onda, que produz um efeito de superposição processando a forma de onda senoidal do eixo X e do eixo Y. A descrição principal do algoritmo é a seguinte:
private const double PI = 3,1415926535897932384626433832795;
private const double PI2 = 6.283185307179586476925286766559
/// <resumo>
;
/// Imagem distorcida da onda sinusoidal
/// </sumário>
/// <param name="srcBmp"></param>
/// <param name="bXDir"></param>
/// <param name="nMultValue">Múltiplo de amplitude da forma de onda</param>
/// <param name="dPhase">Fase inicial da forma de onda, faixa de valores [0-2*PI)</param>
/// <retorna></retorna>
public System.Drawing.Bitmap TwistImage(Bitmap srcBmp,bool bXDir,duplo dMultValue,duplo dPhase)
{
System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width,srcBmp.Height);
// Preenche o fundo do bitmap com branco);
Gráfico System.Drawing.Graphics = System.Drawing.Graphics.FromImage(destBmp);
gráfico.FillRectangle(novo SolidBrush(System.Drawing.Color.White),0,0,destBmp.Width,destBmp.Height);
gráfico.Dispose();
double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width
for(int i=0;i<destBmp.Width;i++)
{
for(int j=0;j<destBmp.Height;j++)
{
duplo dx = 0;
dx = bXDir ? (PI2*(duplo)j)/dBaseAxisLen : (PI2*(duplo)i)/dBaseAxisLen;
dx += dFase;
double dy = Math.Sin(dx);
// Obtém a cor do ponto atual
int nVelhoX = 0,nVelhoY = 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.Height)
{
destBmp.SetPixel(nOldX,nOldY,cor);
}
}
}
return destinoBmp;
}
A imagem de exemplo no início é a superposição de dois efeitos de forma de onda. Os dois efeitos são para a direção do eixo X e a direção do eixo Y, respectivamente. Se você cancelar o preenchimento da cor de fundo da borda, poderá ver o impacto de. o algoritmo nos gráficos, conforme mostrado abaixo:
O código de verificação gerado desta forma se parece muito com o código de verificação do site do Google. Claro, se você estiver interessado, você também pode adicionar outros efeitos de filtro, como alongamento, rotação, mosaico, etc. Mas observe que quanto mais complexo for o código de verificação do site, melhor você deve encontrar um equilíbrio entre velocidade e segurança.