├── captcha.png
├── WebApi_AspDotNetCore2_2_TypeScript
└── Captcha.WebApi
│ ├── Captcha.WebApi
│ ├── ts
│ │ ├── models.js
│ │ ├── models.js.map
│ │ ├── models.ts
│ │ ├── httpService.ts
│ │ └── captcha.ts
│ ├── appsettings.json
│ ├── appsettings.Development.json
│ ├── tsconfig.json
│ ├── Program.cs
│ ├── package-lock.json
│ ├── Views
│ │ └── Index.cshtml
│ ├── Controllers
│ │ ├── DefaultController.cs
│ │ ├── ValuesController.cs
│ │ └── CaptchaController.cs
│ ├── Captcha.WebApi.csproj
│ └── Startup.cs
│ ├── CaptchaService
│ ├── Models
│ │ ├── VerifyResponse.cs
│ │ ├── VerifyRequest.cs
│ │ └── CaptchaInfo.cs
│ ├── Extensions
│ │ ├── ServiceCollectionExtension.cs
│ │ └── DesExtension.cs
│ ├── CaptchaService.csproj
│ ├── ICaptchaFactory.cs
│ └── CaptchaFactory.cs
│ └── Captcha.WebApi.sln
├── WebApi_AspDotNetCore3_0_TypeScript
└── Captcha.WebApi
│ ├── Captcha.WebApi
│ ├── ts
│ │ ├── models.js
│ │ ├── models.js.map
│ │ ├── models.ts
│ │ ├── httpService.ts
│ │ └── captcha.ts
│ ├── wwwroot
│ │ └── js
│ │ │ ├── models.js
│ │ │ ├── models.js.map
│ │ │ ├── httpService.js.map
│ │ │ ├── captcha.js.map
│ │ │ ├── captcha.js
│ │ │ └── httpService.js
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── tsconfig.json
│ ├── Program.cs
│ ├── package-lock.json
│ ├── Views
│ │ └── Index.cshtml
│ ├── Captcha.WebApi.csproj
│ ├── Controllers
│ │ ├── DefaultController.cs
│ │ ├── ValuesController.cs
│ │ └── CaptchaController.cs
│ └── Startup.cs
│ ├── CaptchaService
│ ├── Models
│ │ ├── VerifyResponse.cs
│ │ ├── VerifyRequest.cs
│ │ └── CaptchaInfo.cs
│ ├── Extensions
│ │ ├── ServiceCollectionExtension.cs
│ │ └── DesExtension.cs
│ ├── CaptchaService.csproj
│ ├── ICaptchaFactory.cs
│ └── CaptchaFactory.cs
│ └── Captcha.WebApi.sln
├── WebApi_AspDotNetCore3_1_TypeScript
└── Captcha.WebApi
│ ├── Captcha.WebApi
│ ├── ts
│ │ ├── models.js
│ │ ├── models.js.map
│ │ ├── models.ts
│ │ ├── httpService.ts
│ │ └── captcha.ts
│ ├── wwwroot
│ │ └── js
│ │ │ ├── models.js
│ │ │ ├── models.js.map
│ │ │ ├── httpService.js.map
│ │ │ ├── captcha.js.map
│ │ │ ├── captcha.js
│ │ │ └── httpService.js
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── tsconfig.json
│ ├── Program.cs
│ ├── package-lock.json
│ ├── Views
│ │ └── Index.cshtml
│ ├── Captcha.WebApi.csproj
│ ├── Controllers
│ │ ├── DefaultController.cs
│ │ ├── ValuesController.cs
│ │ └── CaptchaController.cs
│ └── Startup.cs
│ └── Captcha.WebApi.sln
├── WebApi
├── Captcha
│ ├── appsettings.json
│ ├── Models
│ │ ├── VerifyResponse.cs
│ │ ├── VerifyRequest.cs
│ │ └── CaptchaInfo.cs
│ ├── appsettings.Development.json
│ ├── Captcha.csproj
│ ├── Program.cs
│ ├── Controllers
│ │ ├── DefaultController.cs
│ │ └── CaptchaController.cs
│ ├── Startup.cs
│ ├── Views
│ │ └── Index.cshtml
│ ├── Des.cs
│ └── CaptchaFactory.cs
└── Captcha.sln
├── WebApi_AspDotNetCore2_2
└── Captcha.WebApi
│ ├── Captcha.WebApi
│ ├── appsettings.json
│ ├── appsettings.Development.json
│ ├── Captcha.WebApi.csproj
│ ├── Program.cs
│ ├── Controllers
│ │ ├── DefaultController.cs
│ │ ├── ValuesController.cs
│ │ └── CaptchaController.cs
│ ├── Startup.cs
│ └── Views
│ │ └── Index.cshtml
│ ├── CaptchaService
│ ├── Models
│ │ ├── VerifyResponse.cs
│ │ ├── VerifyRequest.cs
│ │ └── CaptchaInfo.cs
│ ├── Extensions
│ │ ├── ServiceCollectionExtension.cs
│ │ └── DesExtension.cs
│ ├── CaptchaService.csproj
│ ├── ICaptchaFactory.cs
│ └── CaptchaFactory.cs
│ └── Captcha.WebApi.sln
├── CaptchaService
├── Models
│ ├── VerifyResponse.cs
│ ├── VerifyRequest.cs
│ └── CaptchaInfo.cs
├── Extensions
│ ├── ServiceCollectionExtension.cs
│ └── DesExtension.cs
├── CaptchaService.csproj
├── ICaptchaFactory.cs
└── CaptchaFactory.cs
├── README.md
├── LICENSE
└── .gitignore
/captcha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PuzzledAlien/Captcha/HEAD/captcha.png
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=models.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=models.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=models.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/models.js:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=models.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/models.js:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=models.js.map
--------------------------------------------------------------------------------
/WebApi/Captcha/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["models.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["models.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["models.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/models.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["../../ts/models.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/models.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["../../ts/models.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Models/VerifyResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Captcha.Models
2 | {
3 | public class VerifyResponse
4 | {
5 | public int Code { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi/Captcha/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/CaptchaService/Models/VerifyResponse.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyResponse
4 | {
5 | public int Code { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.ts:
--------------------------------------------------------------------------------
1 | interface IVerifyRequest {
2 | answer: string,
3 | captcha: string,
4 | }
5 |
6 | interface IVerifyResponse {
7 | code: number,
8 | message: string,
9 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.ts:
--------------------------------------------------------------------------------
1 | interface IVerifyRequest {
2 | answer: string,
3 | captcha: string,
4 | }
5 |
6 | interface IVerifyResponse {
7 | code: number,
8 | message: string,
9 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/models.ts:
--------------------------------------------------------------------------------
1 | interface IVerifyRequest {
2 | answer: string,
3 | captcha: string,
4 | }
5 |
6 | interface IVerifyResponse {
7 | code: number,
8 | message: string,
9 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/Models/VerifyResponse.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyResponse
4 | {
5 | public int Code { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/Models/VerifyResponse.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyResponse
4 | {
5 | public int Code { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/Models/VerifyResponse.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyResponse
4 | {
5 | public int Code { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
--------------------------------------------------------------------------------
/WebApi/Captcha/Models/VerifyRequest.cs:
--------------------------------------------------------------------------------
1 | namespace Captcha.Models
2 | {
3 | public class VerifyRequest
4 | {
5 | ///
6 | /// 答案
7 | ///
8 | public string Answer { get; set; }
9 | ///
10 | /// Cookie中对应Captcha的值
11 | ///
12 | public string Captcha { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CaptchaService/Models/VerifyRequest.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyRequest
4 | {
5 | ///
6 | /// 答案
7 | ///
8 | public string Answer { get; set; }
9 | ///
10 | /// Cookie中对应Captcha的值
11 | ///
12 | public string Captcha { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Captcha.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/CaptchaService/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace CaptchaService.Extensions
4 | {
5 | public static class ServiceCollectionExtension
6 | {
7 | public static void AddCaptchaService(this IServiceCollection services)
8 | {
9 | services.AddSingleton();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/Models/VerifyRequest.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyRequest
4 | {
5 | ///
6 | /// 答案
7 | ///
8 | public string Answer { get; set; }
9 | ///
10 | /// Cookie中对应Captcha的值
11 | ///
12 | public string Captcha { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/Models/VerifyRequest.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyRequest
4 | {
5 | ///
6 | /// 答案
7 | ///
8 | public string Answer { get; set; }
9 | ///
10 | /// Cookie中对应Captcha的值
11 | ///
12 | public string Captcha { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/Models/VerifyRequest.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class VerifyRequest
4 | {
5 | ///
6 | /// 答案
7 | ///
8 | public string Answer { get; set; }
9 | ///
10 | /// Cookie中对应Captcha的值
11 | ///
12 | public string Captcha { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace CaptchaService.Extensions
4 | {
5 | public static class ServiceCollectionExtension
6 | {
7 | public static void AddCaptchaService(this IServiceCollection services)
8 | {
9 | services.AddSingleton();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "noEmitOnError": true,
5 | "removeComments": false,
6 | "sourceMap": true,
7 | "target": "es5",
8 | "outDir": "wwwroot/js",
9 | "lib": [
10 | "es2016",
11 | "dom",
12 | "es5"
13 | ]
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "wwwroot"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "noEmitOnError": true,
5 | "removeComments": false,
6 | "sourceMap": true,
7 | "target": "es5",
8 | "outDir": "wwwroot/js",
9 | "lib": [
10 | "es2016",
11 | "dom",
12 | "es5"
13 | ]
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "wwwroot"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "noEmitOnError": true,
5 | "removeComments": false,
6 | "sourceMap": true,
7 | "target": "es5",
8 | "outDir": "wwwroot/js",
9 | "lib": [
10 | "es2016",
11 | "dom",
12 | "es5"
13 | ]
14 | },
15 | "exclude": [
16 | "node_modules",
17 | "wwwroot"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace CaptchaService.Extensions
4 | {
5 | public static class ServiceCollectionExtension
6 | {
7 | public static void AddCaptchaService(this IServiceCollection services)
8 | {
9 | services.AddSingleton();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace CaptchaService.Extensions
4 | {
5 | public static class ServiceCollectionExtension
6 | {
7 | public static void AddCaptchaService(this IServiceCollection services)
8 | {
9 | services.AddSingleton();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/CaptchaService/CaptchaService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore;
2 | using Microsoft.AspNetCore.Hosting;
3 |
4 | namespace Captcha
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateWebHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
14 | WebHost.CreateDefaultBuilder(args)
15 | .UseStartup();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/CaptchaService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/CaptchaService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/CaptchaService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Captcha.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Models/CaptchaInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Captcha.Models
2 | {
3 | public class CaptchaInfo
4 | {
5 | ///
6 | /// 图片字节
7 | ///
8 | public byte[] Image { get; set; }
9 | ///
10 | /// 图片中显示的字符(经过DES加密)
11 | ///
12 | public string Answer { get; set; }
13 | ///
14 | /// 设计后续有类似问题类的图片验证码
15 | ///
16 | public string Tip { get; set; }
17 | ///
18 | /// 验证码图片文件为类型
19 | ///
20 | public string ContentType { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CaptchaService/Models/CaptchaInfo.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class CaptchaInfo
4 | {
5 | ///
6 | /// 图片字节
7 | ///
8 | public byte[] Image { get; set; }
9 | ///
10 | /// 图片中显示的字符(经过DES加密)
11 | ///
12 | public string Answer { get; set; }
13 | ///
14 | /// 设计后续有类似问题类的图片验证码
15 | ///
16 | public string Tip { get; set; }
17 | ///
18 | /// 验证码图片文件为类型
19 | ///
20 | public string ContentType { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 |
4 | namespace Captcha.WebApi
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IHostBuilder CreateHostBuilder(string[] args) =>
14 | Host.CreateDefaultBuilder(args)
15 | .ConfigureWebHostDefaults(webBuilder =>
16 | {
17 | webBuilder.UseStartup();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 |
4 | namespace Captcha.WebApi
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IHostBuilder CreateHostBuilder(string[] args) =>
14 | Host.CreateDefaultBuilder(args)
15 | .ConfigureWebHostDefaults(webBuilder =>
16 | {
17 | webBuilder.UseStartup();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/Models/CaptchaInfo.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class CaptchaInfo
4 | {
5 | ///
6 | /// 图片字节
7 | ///
8 | public byte[] Image { get; set; }
9 | ///
10 | /// 图片中显示的字符(经过DES加密)
11 | ///
12 | public string Answer { get; set; }
13 | ///
14 | /// 设计后续有类似问题类的图片验证码
15 | ///
16 | public string Tip { get; set; }
17 | ///
18 | /// 验证码图片文件为类型
19 | ///
20 | public string ContentType { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/Models/CaptchaInfo.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class CaptchaInfo
4 | {
5 | ///
6 | /// 图片字节
7 | ///
8 | public byte[] Image { get; set; }
9 | ///
10 | /// 图片中显示的字符(经过DES加密)
11 | ///
12 | public string Answer { get; set; }
13 | ///
14 | /// 设计后续有类似问题类的图片验证码
15 | ///
16 | public string Tip { get; set; }
17 | ///
18 | /// 验证码图片文件为类型
19 | ///
20 | public string ContentType { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/Models/CaptchaInfo.cs:
--------------------------------------------------------------------------------
1 | namespace CaptchaService.Models
2 | {
3 | public class CaptchaInfo
4 | {
5 | ///
6 | /// 图片字节
7 | ///
8 | public byte[] Image { get; set; }
9 | ///
10 | /// 图片中显示的字符(经过DES加密)
11 | ///
12 | public string Answer { get; set; }
13 | ///
14 | /// 设计后续有类似问题类的图片验证码
15 | ///
16 | public string Tip { get; set; }
17 | ///
18 | /// 验证码图片文件为类型
19 | ///
20 | public string ContentType { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace Captcha.WebApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace Captcha.WebApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "requires": true,
3 | "lockfileVersion": 1,
4 | "dependencies": {
5 | "@types/jquery": {
6 | "version": "3.3.29",
7 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.29.tgz",
8 | "integrity": "sha512-FhJvBninYD36v3k6c+bVk1DSZwh7B5Dpb/Pyk3HKVsiohn0nhbefZZ+3JXbWQhFyt0MxSl2jRDdGQPHeOHFXrQ==",
9 | "requires": {
10 | "@types/sizzle": "*"
11 | }
12 | },
13 | "@types/sizzle": {
14 | "version": "2.3.2",
15 | "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
16 | "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg=="
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "requires": true,
3 | "lockfileVersion": 1,
4 | "dependencies": {
5 | "@types/jquery": {
6 | "version": "3.3.29",
7 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.29.tgz",
8 | "integrity": "sha512-FhJvBninYD36v3k6c+bVk1DSZwh7B5Dpb/Pyk3HKVsiohn0nhbefZZ+3JXbWQhFyt0MxSl2jRDdGQPHeOHFXrQ==",
9 | "requires": {
10 | "@types/sizzle": "*"
11 | }
12 | },
13 | "@types/sizzle": {
14 | "version": "2.3.2",
15 | "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
16 | "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg=="
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "requires": true,
3 | "lockfileVersion": 1,
4 | "dependencies": {
5 | "@types/jquery": {
6 | "version": "3.3.35",
7 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.35.tgz",
8 | "integrity": "sha512-pnIELWhHXJ7RgoFylhiTxD+96QlKBJfEx8JCLj963/dh7zBOKFkZ6rlNqbaCcn2JZrsAxCI8WhgRXznBx2iDsA==",
9 | "requires": {
10 | "@types/sizzle": "*"
11 | }
12 | },
13 | "@types/sizzle": {
14 | "version": "2.3.2",
15 | "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
16 | "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg=="
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Controllers/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Microsoft.AspNetCore.Mvc;
3 |
4 | namespace Captcha.Controllers
5 | {
6 | public class DefaultController : Controller
7 | {
8 | [HttpGet, Route("index")]
9 | public IActionResult Index()
10 | {
11 | return View("/Views/Index.cshtml");
12 | }
13 |
14 | ///
15 | /// 返回验证码图片
16 | ///
17 | ///
18 | [HttpGet, Route("captcha")]
19 | public async Task GetCaptcha()
20 | {
21 | var model = await CaptchaFactory.Intance.CreateAsync();
22 | Response.Cookies.Append("Captcha", model.Answer);
23 | return File(model.Image, model.ContentType);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Views/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @{
3 | Layout = null;
4 | }
5 |
6 |
7 |
8 |
9 |
10 |
11 | Index
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Views/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @{
3 | Layout = null;
4 | }
5 |
6 |
7 |
8 |
9 |
10 |
11 | Index
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Views/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @{
3 | Layout = null;
4 | }
5 |
6 |
7 |
8 |
9 |
10 |
11 | Index
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/httpService.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"httpService.js","sourceRoot":"","sources":["../../ts/httpService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;IAGI;IAEA,CAAC;IAEK,8BAAQ,GAAd,UAAkB,GAAW;;;;;;;wBAEN,qBAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAA;;wBAA3C,MAAM,GAAG,SAAkC;wBACjD,sBAAO,MAAW,EAAC;;;wBAEnB,KAAK,CAAC,GAAC,CAAC,CAAC;;4BAEb,sBAAO,IAAI,EAAC;;;;KACf;IAEK,+BAAS,GAAf,UAAmB,GAAW,EAAE,IAAU;;;;;;;wBAEnB,qBAAM,CAAC,CAAC,IAAI,CAAC;gCACxB,GAAG,EAAE,GAAG;gCACR,IAAI,EAAE,MAAM;gCACZ,QAAQ,EAAE,MAAM;gCAChB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gCAC1B,WAAW,EAAE,iCAAiC;6BACjD,CAAC,EAAA;;wBANI,MAAM,GAAG,SAMb;wBACF,sBAAO,MAAW,EAAC;;;wBAEnB,KAAK,CAAC,GAAC,CAAC,CAAC;;4BAEb,sBAAO,IAAI,EAAC;;;;KACf;IA9BsB,oBAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;IAgCxD,kBAAC;CAAA,AAjCD,IAiCC"}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/httpService.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"httpService.js","sourceRoot":"","sources":["../../ts/httpService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;IAGI;IAEA,CAAC;IAEK,8BAAQ,GAAd,UAAkB,GAAW;;;;;;;wBAEN,qBAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAA;;wBAA3C,MAAM,GAAG,SAAkC;wBACjD,sBAAO,MAAW,EAAC;;;wBAEnB,KAAK,CAAC,GAAC,CAAC,CAAC;;4BAEb,sBAAO,IAAI,EAAC;;;;KACf;IAEK,+BAAS,GAAf,UAAmB,GAAW,EAAE,IAAU;;;;;;;wBAEnB,qBAAM,CAAC,CAAC,IAAI,CAAC;gCACxB,GAAG,EAAE,GAAG;gCACR,IAAI,EAAE,MAAM;gCACZ,QAAQ,EAAE,MAAM;gCAChB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gCAC1B,WAAW,EAAE,iCAAiC;6BACjD,CAAC,EAAA;;wBANI,MAAM,GAAG,SAMb;wBACF,sBAAO,MAAW,EAAC;;;wBAEnB,KAAK,CAAC,GAAC,CAAC,CAAC;;4BAEb,sBAAO,IAAI,EAAC;;;;KACf;IA9BsB,oBAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;IAgCxD,kBAAC;CAAA,AAjCD,IAiCC"}
--------------------------------------------------------------------------------
/CaptchaService/ICaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService.Models;
3 |
4 | namespace CaptchaService
5 | {
6 | public interface ICaptchaFactory
7 | {
8 | ///
9 | /// 生成验证码图片
10 | ///
11 | /// 图片中出现字符数
12 | /// 图片宽度
13 | /// 图片高度
14 | ///
15 | Task CreateAsync(int charCount = 4, int width = 85, int height = 40);
16 | ///
17 | /// 比对验证码
18 | ///
19 | ///
20 | /// 单位秒,超时时间默认600秒(5分钟)
21 | ///
22 | Task VerifyAsync(VerifyRequest model, int timeOut = 600);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/ICaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using CaptchaService.Models;
4 |
5 | namespace CaptchaService
6 | {
7 | public interface ICaptchaFactory
8 | {
9 | ///
10 | /// 生成验证码图片
11 | ///
12 | /// 图片中出现字符数
13 | /// 图片宽度
14 | /// 图片高度
15 | ///
16 | Task CreateAsync(int charCount = 4, int width = 85, int height = 40);
17 | ///
18 | /// 比对验证码
19 | ///
20 | ///
21 | /// 单位秒,超时时间默认600秒(5分钟)
22 | ///
23 | Task VerifyAsync(VerifyRequest model, int timeOut = 600);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/ICaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using CaptchaService.Models;
4 |
5 | namespace CaptchaService
6 | {
7 | public interface ICaptchaFactory
8 | {
9 | ///
10 | /// 生成验证码图片
11 | ///
12 | /// 图片中出现字符数
13 | /// 图片宽度
14 | /// 图片高度
15 | ///
16 | Task CreateAsync(int charCount = 4, int width = 85, int height = 40);
17 | ///
18 | /// 比对验证码
19 | ///
20 | ///
21 | /// 单位秒,超时时间默认600秒(5分钟)
22 | ///
23 | Task VerifyAsync(VerifyRequest model, int timeOut = 600);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/ICaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using CaptchaService.Models;
4 |
5 | namespace CaptchaService
6 | {
7 | public interface ICaptchaFactory
8 | {
9 | ///
10 | /// 生成验证码图片
11 | ///
12 | /// 图片中出现字符数
13 | /// 图片宽度
14 | /// 图片高度
15 | ///
16 | Task CreateAsync(int charCount = 4, int width = 85, int height = 40);
17 | ///
18 | /// 比对验证码
19 | ///
20 | ///
21 | /// 单位秒,超时时间默认600秒(5分钟)
22 | ///
23 | Task VerifyAsync(VerifyRequest model, int timeOut = 600);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Captcha
2 | 项目中包含一个页面,运行之后,可访问路由“/Index”,进行自测,页面如下图所示
3 |
4 | 
5 |
6 | ## 使用方式
7 | 嵌入图片,部署之后访问“/captcha”,可直接加载一张图片
8 |
9 | 接口:
10 |
11 | 1、api/captcha :返回图片byte[]
12 |
13 | 2、api/captcha/verify:校验验证码
14 |
15 | ## 注意
16 |
17 | 如果运行在Windows环境,是完成ok的。[System.Drawing.Common](https://www.nuget.org/packages/System.Drawing.Common)是完美的解决方案。
18 |
19 | 如果现在你想要部署在Ubuntu或者Docker环境下,你需要安装 对应平台的 `GDI +`相关依赖项。
20 |
21 | Ubuntu需要安装的依赖库如下
22 |
23 | ```
24 | sudo apt install libc6-dev
25 | sudo apt install libgdiplus
26 | ```
27 |
28 | ## 下一步计划
29 |
30 | ### 计划1
31 | .Net Core图形处理开源组件有更多选项,下一步计划都试一试
32 |
33 | - [ImageSharp](https://github.com/SixLabors/ImageSharp)
34 | - [Magick.NET](https://github.com/dlemstra/Magick.NET)
35 | - [SkiaSharp](https://github.com/mono/SkiaSharp)
36 |
37 | ### ~~计划2~~
38 | ~~尝试.Net Core 2.2,将Captcha独立成.Net Standard类库,并借助微软自带DI解耦CaptchaFactory~~
39 |
40 | 计划2已完成
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Captcha.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 | InProcess
6 | 3.6
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Captcha.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | InProcess
6 | 3.8
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/httpService.ts:
--------------------------------------------------------------------------------
1 | class HttpService {
2 | public static readonly instance = new HttpService();
3 |
4 | private constructor() {
5 |
6 | }
7 |
8 | async getAsync(url: string): Promise {
9 | try {
10 | const result = await $.ajax(url, { type: "GET" });
11 | return result as T;
12 | } catch (e) {
13 | alert(e);
14 | }
15 | return null;
16 | }
17 |
18 | async postAsync(url: string, data?: any): Promise {
19 | try {
20 | const result = await $.ajax({
21 | url: url,
22 | type: "POST",
23 | dataType: "json",
24 | data: JSON.stringify(data),
25 | contentType: 'application/json; charset=utf-8'
26 | });
27 | return result as T;
28 | } catch (e) {
29 | alert(e);
30 | }
31 | return null;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/httpService.ts:
--------------------------------------------------------------------------------
1 | class HttpService {
2 | public static readonly instance = new HttpService();
3 |
4 | private constructor() {
5 |
6 | }
7 |
8 | async getAsync(url: string): Promise {
9 | try {
10 | const result = await $.ajax(url, { type: "GET" });
11 | return result as T;
12 | } catch (e) {
13 | alert(e);
14 | }
15 | return null;
16 | }
17 |
18 | async postAsync(url: string, data?: any): Promise {
19 | try {
20 | const result = await $.ajax({
21 | url: url,
22 | type: "POST",
23 | dataType: "json",
24 | data: JSON.stringify(data),
25 | contentType: 'application/json; charset=utf-8'
26 | });
27 | return result as T;
28 | } catch (e) {
29 | alert(e);
30 | }
31 | return null;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/httpService.ts:
--------------------------------------------------------------------------------
1 | class HttpService {
2 | public static readonly instance = new HttpService();
3 |
4 | private constructor() {
5 |
6 | }
7 |
8 | async getAsync(url: string): Promise {
9 | try {
10 | const result = await $.ajax(url, { type: "GET" });
11 | return result as T;
12 | } catch (e) {
13 | alert(e);
14 | }
15 | return null;
16 | }
17 |
18 | async postAsync(url: string, data?: any): Promise {
19 | try {
20 | const result = await $.ajax({
21 | url: url,
22 | type: "POST",
23 | dataType: "json",
24 | data: JSON.stringify(data),
25 | contentType: 'application/json; charset=utf-8'
26 | });
27 | return result as T;
28 | } catch (e) {
29 | alert(e);
30 | }
31 | return null;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/WebApi/Captcha/Controllers/CaptchaController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Captcha.Models;
4 |
5 | namespace Captcha.Controllers
6 | {
7 | [ApiController]
8 | public class CaptchaController : ControllerBase
9 | {
10 | ///
11 | /// 获取验证码
12 | ///
13 | ///
14 | [HttpGet, Route("api/captcha")]
15 | public async Task GetCaptcha()
16 | {
17 | var model = await CaptchaFactory.Intance.CreateAsync();
18 | return model;
19 | }
20 |
21 | ///
22 | /// 验证码的校验
23 | ///
24 | ///
25 | ///
26 | [HttpPost, Route("api/captcha/verify")]
27 | public async Task Verify([FromBody] VerifyRequest model)
28 | {
29 | var response = await CaptchaFactory.Intance.VerifyAsync(model);
30 |
31 | return response;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Controllers/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace Captcha.WebApi.Controllers
6 | {
7 | public class DefaultController : Controller
8 | {
9 | private readonly ICaptchaFactory _captchaFactory;
10 | public DefaultController(ICaptchaFactory captchaFactory)
11 | {
12 | _captchaFactory = captchaFactory;
13 | }
14 |
15 | [HttpGet, Route("index")]
16 | public IActionResult Index()
17 | {
18 | return View("/Views/Index.cshtml");
19 | }
20 |
21 | ///
22 | /// 返回验证码图片
23 | ///
24 | ///
25 | [HttpGet, Route("captcha")]
26 | public async Task GetCaptcha()
27 | {
28 | var model = await _captchaFactory.CreateAsync();
29 | Response.Cookies.Append("Captcha", model.Answer);
30 | return File(model.Image, model.ContentType);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace Captcha.WebApi.Controllers
6 | {
7 | public class DefaultController : Controller
8 | {
9 | private readonly ICaptchaFactory _captchaFactory;
10 | public DefaultController(ICaptchaFactory captchaFactory)
11 | {
12 | _captchaFactory = captchaFactory;
13 | }
14 |
15 | [HttpGet, Route("index")]
16 | public IActionResult Index()
17 | {
18 | return View("/Views/Index.cshtml");
19 | }
20 |
21 | ///
22 | /// 返回验证码图片
23 | ///
24 | ///
25 | [HttpGet, Route("captcha")]
26 | public async Task GetCaptcha()
27 | {
28 | var model = await _captchaFactory.CreateAsync();
29 | Response.Cookies.Append("Captcha", model.Answer);
30 | return File(model.Image, model.ContentType);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace Captcha.WebApi.Controllers
6 | {
7 | public class DefaultController : Controller
8 | {
9 | private readonly ICaptchaFactory _captchaFactory;
10 | public DefaultController(ICaptchaFactory captchaFactory)
11 | {
12 | _captchaFactory = captchaFactory;
13 | }
14 |
15 | [HttpGet, Route("index")]
16 | public IActionResult Index()
17 | {
18 | return View("/Views/Index.cshtml");
19 | }
20 |
21 | ///
22 | /// 返回验证码图片
23 | ///
24 | ///
25 | [HttpGet, Route("captcha")]
26 | public async Task GetCaptcha()
27 | {
28 | var model = await _captchaFactory.CreateAsync();
29 | Response.Cookies.Append("Captcha", model.Answer);
30 | return File(model.Image, model.ContentType);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace Captcha.WebApi.Controllers
6 | {
7 | public class DefaultController : Controller
8 | {
9 | private readonly ICaptchaFactory _captchaFactory;
10 | public DefaultController(ICaptchaFactory captchaFactory)
11 | {
12 | _captchaFactory = captchaFactory;
13 | }
14 |
15 | [HttpGet, Route("index")]
16 | public IActionResult Index()
17 | {
18 | return View("/Views/Index.cshtml");
19 | }
20 |
21 | ///
22 | /// 返回验证码图片
23 | ///
24 | ///
25 | [HttpGet, Route("captcha")]
26 | public async Task GetCaptcha()
27 | {
28 | var model = await _captchaFactory.CreateAsync();
29 | Response.Cookies.Append("Captcha", model.Answer);
30 | return File(model.Image, model.ContentType);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Xu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/captcha.ts:
--------------------------------------------------------------------------------
1 | $(document).ready(async () => {
2 |
3 | $("#btnCaptcha").click(async () => {
4 | //调用验证码校验方法
5 | const answer = encodeURI($("#txtCaptcha").val() as string);
6 |
7 | const captcha = encodeURI(getCookie("Captcha"));
8 |
9 | var request: IVerifyRequest = {
10 | answer: answer,
11 | captcha: captcha
12 | };
13 |
14 | var result = await verifyAsync(request);
15 | alert(`message : ${result.message}, code : ${result.code}`);
16 | });
17 | });
18 | async function verifyAsync(request: IVerifyRequest): Promise {
19 | const url = "api/captcha/verify";
20 | const result = await HttpService.instance.postAsync(url, request);
21 |
22 | return result;
23 | }
24 |
25 | function getCookie(name) {
26 | //获取Cookie值
27 | const strCookie = document.cookie;
28 | const arrCookie = strCookie.split("; ");
29 | for (let i = 0; i < arrCookie.length; i++) {
30 | const arr = arrCookie[i].split("=");
31 | if (arr[0] === name) return arr[1];
32 | }
33 | return "";
34 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Microsoft.AspNetCore.Mvc;
3 |
4 | namespace Captcha.WebApi.Controllers
5 | {
6 | [Route("api/[controller]")]
7 | [ApiController]
8 | public class ValuesController : ControllerBase
9 | {
10 | // GET api/values
11 | [HttpGet]
12 | public ActionResult> Get()
13 | {
14 | return new string[] { "value1", "value2" };
15 | }
16 |
17 | // GET api/values/5
18 | [HttpGet("{id}")]
19 | public ActionResult Get(int id)
20 | {
21 | return "value";
22 | }
23 |
24 | // POST api/values
25 | [HttpPost]
26 | public void Post([FromBody] string value)
27 | {
28 | }
29 |
30 | // PUT api/values/5
31 | [HttpPut("{id}")]
32 | public void Put(int id, [FromBody] string value)
33 | {
34 | }
35 |
36 | // DELETE api/values/5
37 | [HttpDelete("{id}")]
38 | public void Delete(int id)
39 | {
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/captcha.ts:
--------------------------------------------------------------------------------
1 | $(document).ready(async () => {
2 |
3 | $("#btnCaptcha").click(async () => {
4 | //调用验证码校验方法
5 | const answer = encodeURI($("#txtCaptcha").val() as string);
6 |
7 | const captcha = encodeURI(getCookie("Captcha"));
8 |
9 | var request: IVerifyRequest = {
10 | answer: answer,
11 | captcha: captcha
12 | };
13 |
14 | var result = await verifyAsync(request);
15 | alert(`message : ${result.message}, code : ${result.code}`);
16 | });
17 | });
18 | async function verifyAsync(request: IVerifyRequest): Promise {
19 | const url = "api/captcha/verify";
20 | const result = await HttpService.instance.postAsync(url, request);
21 |
22 | return result;
23 | }
24 |
25 | function getCookie(name) {
26 | //获取Cookie值
27 | const strCookie = document.cookie;
28 | const arrCookie = strCookie.split("; ");
29 | for (let i = 0; i < arrCookie.length; i++) {
30 | const arr = arrCookie[i].split("=");
31 | if (arr[0] === name) return arr[1];
32 | }
33 | return "";
34 | }
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Microsoft.AspNetCore.Mvc;
3 |
4 | namespace Captcha.WebApi.Controllers
5 | {
6 | [Route("api/[controller]")]
7 | [ApiController]
8 | public class ValuesController : ControllerBase
9 | {
10 | // GET api/values
11 | [HttpGet]
12 | public ActionResult> Get()
13 | {
14 | return new string[] { "value1", "value2" };
15 | }
16 |
17 | // GET api/values/5
18 | [HttpGet("{id}")]
19 | public ActionResult Get(int id)
20 | {
21 | return "value";
22 | }
23 |
24 | // POST api/values
25 | [HttpPost]
26 | public void Post([FromBody] string value)
27 | {
28 | }
29 |
30 | // PUT api/values/5
31 | [HttpPut("{id}")]
32 | public void Put(int id, [FromBody] string value)
33 | {
34 | }
35 |
36 | // DELETE api/values/5
37 | [HttpDelete("{id}")]
38 | public void Delete(int id)
39 | {
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/ts/captcha.ts:
--------------------------------------------------------------------------------
1 | $(document).ready(async () => {
2 |
3 | $("#btnCaptcha").click(async () => {
4 | //调用验证码校验方法
5 | const answer = encodeURI($("#txtCaptcha").val() as string);
6 |
7 | const captcha = encodeURI(getCookie("Captcha"));
8 |
9 | var request: IVerifyRequest = {
10 | answer: answer,
11 | captcha: captcha
12 | };
13 |
14 | var result = await verifyAsync(request);
15 | alert(`message : ${result.message}, code : ${result.code}`);
16 | });
17 | });
18 | async function verifyAsync(request: IVerifyRequest): Promise {
19 | const url = "api/captcha/verify";
20 | const result = await HttpService.instance.postAsync(url, request);
21 |
22 | return result;
23 | }
24 |
25 | function getCookie(name) {
26 | //获取Cookie值
27 | const strCookie = document.cookie;
28 | const arrCookie = strCookie.split("; ");
29 | for (let i = 0; i < arrCookie.length; i++) {
30 | const arr = arrCookie[i].split("=");
31 | if (arr[0] === name) return arr[1];
32 | }
33 | return "";
34 | }
--------------------------------------------------------------------------------
/WebApi/Captcha.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2026
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Captcha", "Captcha\Captcha.csproj", "{D883E45A-C661-4D49-BB56-2712F2F44022}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D883E45A-C661-4D49-BB56-2712F2F44022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {D883E45A-C661-4D49-BB56-2712F2F44022}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {D883E45A-C661-4D49-BB56-2712F2F44022}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {D883E45A-C661-4D49-BB56-2712F2F44022}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {AC903680-7CE6-46D0-8DB6-E81447C7AB45}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Captcha.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 | 3.1
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/captcha.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../ts/captcha.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAiCC;AAjCD,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;;;QAEd,CAAC,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC;;;;;wBAEb,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,GAAG,EAAY,CAAC,CAAC;wBAErD,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;wBAE5C,OAAO,GAAmB;4BAC1B,MAAM,EAAE,MAAM;4BACd,OAAO,EAAE,OAAO;yBACnB,CAAC;wBAEW,qBAAM,WAAW,CAAC,OAAO,CAAC,EAAA;;wBAAnC,MAAM,GAAG,SAA0B;wBACvC,KAAK,CAAC,eAAa,MAAM,CAAC,OAAO,iBAAY,MAAM,CAAC,IAAM,CAAC,CAAC;;;;aAC/D,CAAC,CAAC;;;KACN,CAAC,CAAC;AACH,SAAe,WAAW,CAAC,OAAuB;;;;;;oBACxC,GAAG,GAAG,oBAAoB,CAAC;oBAClB,qBAAM,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAkB,GAAG,EAAE,OAAO,CAAC,EAAA;;oBAA5E,MAAM,GAAG,SAAmE;oBAElF,sBAAO,MAAM,EAAC;;;;CACjB;AAED,SAAS,SAAS,CAAC,IAAI;IACnB,WAAW;IACX,IAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,IAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACvC,IAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;KACtC;IACD,OAAO,EAAE,CAAC;AACd,CAAC"}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/captcha.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"captcha.js","sourceRoot":"","sources":["../../ts/captcha.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAiCC;AAjCD,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;;;QAEd,CAAC,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC;;;;;wBAEb,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,GAAG,EAAY,CAAC,CAAC;wBAErD,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;wBAE5C,OAAO,GAAmB;4BAC1B,MAAM,EAAE,MAAM;4BACd,OAAO,EAAE,OAAO;yBACnB,CAAC;wBAEW,qBAAM,WAAW,CAAC,OAAO,CAAC,EAAA;;wBAAnC,MAAM,GAAG,SAA0B;wBACvC,KAAK,CAAC,eAAa,MAAM,CAAC,OAAO,iBAAY,MAAM,CAAC,IAAM,CAAC,CAAC;;;;aAC/D,CAAC,CAAC;;;KACN,CAAC,CAAC;AACH,SAAe,WAAW,CAAC,OAAuB;;;;;;oBACxC,GAAG,GAAG,oBAAoB,CAAC;oBAClB,qBAAM,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAkB,GAAG,EAAE,OAAO,CAAC,EAAA;;oBAA5E,MAAM,GAAG,SAAmE;oBAElF,sBAAO,MAAM,EAAC;;;;CACjB;AAED,SAAS,SAAS,CAAC,IAAI;IACnB,WAAW;IACX,IAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAClC,IAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACvC,IAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;KACtC;IACD,OAAO,EAAE,CAAC;AACd,CAAC"}
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace Captcha.WebApi.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | [ApiController]
11 | public class ValuesController : ControllerBase
12 | {
13 | // GET api/values
14 | [HttpGet]
15 | public ActionResult> Get()
16 | {
17 | return new string[] { "value1", "value2" };
18 | }
19 |
20 | // GET api/values/5
21 | [HttpGet("{id}")]
22 | public ActionResult Get(int id)
23 | {
24 | return "value";
25 | }
26 |
27 | // POST api/values
28 | [HttpPost]
29 | public void Post([FromBody] string value)
30 | {
31 | }
32 |
33 | // PUT api/values/5
34 | [HttpPut("{id}")]
35 | public void Put(int id, [FromBody] string value)
36 | {
37 | }
38 |
39 | // DELETE api/values/5
40 | [HttpDelete("{id}")]
41 | public void Delete(int id)
42 | {
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace Captcha.WebApi.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | [ApiController]
11 | public class ValuesController : ControllerBase
12 | {
13 | // GET api/values
14 | [HttpGet]
15 | public ActionResult> Get()
16 | {
17 | return new string[] { "value1", "value2" };
18 | }
19 |
20 | // GET api/values/5
21 | [HttpGet("{id}")]
22 | public ActionResult Get(int id)
23 | {
24 | return "value";
25 | }
26 |
27 | // POST api/values
28 | [HttpPost]
29 | public void Post([FromBody] string value)
30 | {
31 | }
32 |
33 | // PUT api/values/5
34 | [HttpPut("{id}")]
35 | public void Put(int id, [FromBody] string value)
36 | {
37 | }
38 |
39 | // DELETE api/values/5
40 | [HttpDelete("{id}")]
41 | public void Delete(int id)
42 | {
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 |
7 | namespace Captcha
8 | {
9 | public class Startup
10 | {
11 | public Startup(IConfiguration configuration)
12 | {
13 | Configuration = configuration;
14 | }
15 |
16 | public IConfiguration Configuration { get; }
17 |
18 | // This method gets called by the runtime. Use this method to add services to the container.
19 | public void ConfigureServices(IServiceCollection services)
20 | {
21 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
22 | }
23 |
24 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
25 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
26 | {
27 | if (env.IsDevelopment())
28 | {
29 | app.UseDeveloperExceptionPage();
30 | }
31 | else
32 | {
33 | app.UseHsts();
34 | }
35 |
36 | app.UseHttpsRedirection();
37 | app.UseMvc();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Controllers/CaptchaController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using CaptchaService.Models;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace Captcha.WebApi.Controllers
7 | {
8 | [ApiController]
9 | public class CaptchaController : ControllerBase
10 | {
11 | private readonly ICaptchaFactory _captchaFactory;
12 | public CaptchaController(ICaptchaFactory captchaFactory)
13 | {
14 | _captchaFactory = captchaFactory;
15 | }
16 |
17 | ///
18 | /// 获取验证码
19 | ///
20 | ///
21 | [HttpGet, Route("api/captcha")]
22 | public async Task GetCaptcha()
23 | {
24 | var model = await _captchaFactory.CreateAsync();
25 | return model;
26 | }
27 |
28 | ///
29 | /// 验证码的校验
30 | ///
31 | ///
32 | ///
33 | [HttpPost, Route("api/captcha/verify")]
34 | public async Task Verify([FromBody] VerifyRequest model)
35 | {
36 | var response = await _captchaFactory.VerifyAsync(model);
37 | return response;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/CaptchaController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using CaptchaService.Models;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace Captcha.WebApi.Controllers
7 | {
8 | [ApiController]
9 | public class CaptchaController : ControllerBase
10 | {
11 | private readonly ICaptchaFactory _captchaFactory;
12 | public CaptchaController(ICaptchaFactory captchaFactory)
13 | {
14 | _captchaFactory = captchaFactory;
15 | }
16 |
17 | ///
18 | /// 获取验证码
19 | ///
20 | ///
21 | [HttpGet, Route("api/captcha")]
22 | public async Task GetCaptcha()
23 | {
24 | var model = await _captchaFactory.CreateAsync();
25 | return model;
26 | }
27 |
28 | ///
29 | /// 验证码的校验
30 | ///
31 | ///
32 | ///
33 | [HttpPost, Route("api/captcha/verify")]
34 | public async Task Verify([FromBody] VerifyRequest model)
35 | {
36 | var response = await _captchaFactory.VerifyAsync(model);
37 | return response;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/CaptchaController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using CaptchaService.Models;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace Captcha.WebApi.Controllers
7 | {
8 | [ApiController]
9 | public class CaptchaController : ControllerBase
10 | {
11 | private readonly ICaptchaFactory _captchaFactory;
12 | public CaptchaController(ICaptchaFactory captchaFactory)
13 | {
14 | _captchaFactory = captchaFactory;
15 | }
16 |
17 | ///
18 | /// 获取验证码
19 | ///
20 | ///
21 | [HttpGet, Route("api/captcha")]
22 | public async Task GetCaptcha()
23 | {
24 | var model = await _captchaFactory.CreateAsync();
25 | return model;
26 | }
27 |
28 | ///
29 | /// 验证码的校验
30 | ///
31 | ///
32 | ///
33 | [HttpPost, Route("api/captcha/verify")]
34 | public async Task Verify([FromBody] VerifyRequest model)
35 | {
36 | var response = await _captchaFactory.VerifyAsync(model);
37 | return response;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Controllers/CaptchaController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using CaptchaService;
3 | using CaptchaService.Models;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace Captcha.WebApi.Controllers
7 | {
8 | [ApiController]
9 | public class CaptchaController : ControllerBase
10 | {
11 | private readonly ICaptchaFactory _captchaFactory;
12 | public CaptchaController(ICaptchaFactory captchaFactory)
13 | {
14 | _captchaFactory = captchaFactory;
15 | }
16 |
17 | ///
18 | /// 获取验证码
19 | ///
20 | ///
21 | [HttpGet, Route("api/captcha")]
22 | public async Task GetCaptcha()
23 | {
24 | var model = await _captchaFactory.CreateAsync();
25 | return model;
26 | }
27 |
28 | ///
29 | /// 验证码的校验
30 | ///
31 | ///
32 | ///
33 | [HttpPost, Route("api/captcha/verify")]
34 | public async Task Verify([FromBody] VerifyRequest model)
35 | {
36 | var response = await _captchaFactory.VerifyAsync(model);
37 | return response;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using CaptchaService.Extensions;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace Captcha.WebApi
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | //使用验证码服务
29 | services.AddCaptchaService();
30 |
31 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
32 | }
33 |
34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
36 | {
37 | if (env.IsDevelopment())
38 | {
39 | app.UseDeveloperExceptionPage();
40 | }
41 |
42 | app.UseMvc();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using CaptchaService.Extensions;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.Hosting;
7 |
8 | namespace Captcha.WebApi
9 | {
10 | public class Startup
11 | {
12 | public Startup(IConfiguration configuration)
13 | {
14 | Configuration = configuration;
15 | }
16 |
17 | public IConfiguration Configuration { get; }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | public void ConfigureServices(IServiceCollection services)
21 | {
22 | //使用验证码服务
23 | services.AddCaptchaService();
24 |
25 | services.AddControllersWithViews();
26 | }
27 |
28 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
29 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
30 | {
31 | if (env.IsDevelopment())
32 | {
33 | app.UseDeveloperExceptionPage();
34 | }
35 |
36 | app.UseStaticFiles();
37 |
38 | app.UseRouting();
39 |
40 | app.UseAuthorization();
41 |
42 | app.UseEndpoints(endpoints =>
43 | {
44 | endpoints.MapControllers();
45 | });
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using CaptchaService.Extensions;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.Hosting;
7 |
8 | namespace Captcha.WebApi
9 | {
10 | public class Startup
11 | {
12 | public Startup(IConfiguration configuration)
13 | {
14 | Configuration = configuration;
15 | }
16 |
17 | public IConfiguration Configuration { get; }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | public void ConfigureServices(IServiceCollection services)
21 | {
22 | //使用验证码服务
23 | services.AddCaptchaService();
24 |
25 | services.AddControllersWithViews();
26 | }
27 |
28 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
29 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
30 | {
31 | if (env.IsDevelopment())
32 | {
33 | app.UseDeveloperExceptionPage();
34 | }
35 |
36 | app.UseStaticFiles();
37 |
38 | app.UseRouting();
39 |
40 | app.UseAuthorization();
41 |
42 | app.UseEndpoints(endpoints =>
43 | {
44 | endpoints.MapControllers();
45 | });
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using CaptchaService.Extensions;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace Captcha.WebApi
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | //使用验证码服务
29 | services.AddCaptchaService();
30 |
31 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
32 | }
33 |
34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
36 | {
37 | app.UseStaticFiles();
38 |
39 | if (env.IsDevelopment())
40 | {
41 | app.UseDeveloperExceptionPage();
42 | }
43 |
44 | app.UseMvc();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Captcha.WebApi", "Captcha.WebApi\Captcha.WebApi.csproj", "{462A9857-9067-49BB-819F-EE263DBAEF76}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaptchaService", "CaptchaService\CaptchaService.csproj", "{C630DC79-753B-4836-A680-6BA50CC02951}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {FA4E7EAE-1CC2-4A19-9294-99544D680A5E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/Captcha.WebApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Captcha.WebApi", "Captcha.WebApi\Captcha.WebApi.csproj", "{462A9857-9067-49BB-819F-EE263DBAEF76}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaptchaService", "CaptchaService\CaptchaService.csproj", "{C630DC79-753B-4836-A680-6BA50CC02951}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {FA4E7EAE-1CC2-4A19-9294-99544D680A5E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Captcha.WebApi", "Captcha.WebApi\Captcha.WebApi.csproj", "{462A9857-9067-49BB-819F-EE263DBAEF76}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaptchaService", "CaptchaService\CaptchaService.csproj", "{C630DC79-753B-4836-A680-6BA50CC02951}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {C630DC79-753B-4836-A680-6BA50CC02951}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {C630DC79-753B-4836-A680-6BA50CC02951}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {FA4E7EAE-1CC2-4A19-9294-99544D680A5E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30011.22
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Captcha.WebApi", "Captcha.WebApi\Captcha.WebApi.csproj", "{462A9857-9067-49BB-819F-EE263DBAEF76}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CaptchaService", "..\..\CaptchaService\CaptchaService.csproj", "{3BB39B54-703A-480A-A1F5-72A4098B6ED5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {462A9857-9067-49BB-819F-EE263DBAEF76}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {3BB39B54-703A-480A-A1F5-72A4098B6ED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {3BB39B54-703A-480A-A1F5-72A4098B6ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {3BB39B54-703A-480A-A1F5-72A4098B6ED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {3BB39B54-703A-480A-A1F5-72A4098B6ED5}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {FA4E7EAE-1CC2-4A19-9294-99544D680A5E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Views/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @{
3 | Layout = null;
4 | }
5 |
6 |
7 |
8 |
9 |
10 |
11 | Index
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
22 |
23 |
24 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/Captcha.WebApi/Views/Index.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @{
3 | Layout = null;
4 | }
5 |
6 |
7 |
8 |
9 |
10 |
11 | Index
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
21 |
22 |
23 |
24 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/WebApi/Captcha/Des.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Captcha
9 | {
10 | ///
11 | /// DES加密解密
12 | ///
13 | public class Des
14 | {
15 | ///
16 | /// 加密密钥
17 | ///
18 | private const string SecretKey = "LOVEROSE";
19 | ///
20 | /// 默认UTF8编码
21 | ///
22 | private static readonly Encoding Default = Encoding.UTF8;
23 |
24 | ///
25 | /// DES 加密
26 | ///
27 | ///
28 | ///
29 | public static async Task EncryptAsync(string val)
30 | {
31 | if (string.IsNullOrEmpty(val))
32 | {
33 | return string.Empty;
34 | }
35 |
36 | using (var p = new DESCryptoServiceProvider())
37 | {
38 | p.IV = Default.GetBytes(SecretKey);
39 | p.Key = Default.GetBytes(SecretKey);
40 | using (var ct = p.CreateEncryptor(p.IV, p.Key))
41 | {
42 | var temp = Default.GetBytes(val);
43 | using (var ms = new MemoryStream())
44 | {
45 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
46 | {
47 | await cs.WriteAsync(temp, 0, temp.Length);
48 | await cs.FlushAsync();
49 | cs.Close();
50 | }
51 |
52 | return Convert.ToBase64String(ms.ToArray());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// DES 解密
60 | ///
61 | ///
62 | ///
63 | public static async Task DecryptAsync(string val)
64 | {
65 | if (string.IsNullOrEmpty(val))
66 | {
67 | return string.Empty;
68 | }
69 |
70 | using (var p = new DESCryptoServiceProvider())
71 | {
72 | p.IV = Default.GetBytes(SecretKey);
73 | p.Key = Default.GetBytes(SecretKey);
74 | using (var ct = p.CreateDecryptor(p.IV, p.Key))
75 | {
76 | val = WebUtility.UrlDecode(val);
77 | val = WebUtility.UrlDecode(val);
78 | var temp = Convert.FromBase64String(val);
79 | using (var ms = new MemoryStream())
80 | {
81 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
82 | {
83 | await cs.WriteAsync(temp, 0, temp.Length);
84 | await cs.FlushAsync();
85 | cs.Close();
86 | }
87 | return Default.GetString(ms.ToArray());
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/CaptchaService/Extensions/DesExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CaptchaService.Extensions
9 | {
10 | ///
11 | /// DES加密解密
12 | ///
13 | public static class DesExtension
14 | {
15 | ///
16 | /// 加密密钥
17 | ///
18 | private const string SecretKey = "LOVEROSE";
19 | ///
20 | /// 默认UTF8编码
21 | ///
22 | private static readonly Encoding Default = Encoding.UTF8;
23 |
24 | ///
25 | /// DES 加密
26 | ///
27 | ///
28 | ///
29 | public static async Task EncryptAsync(this string val)
30 | {
31 | if (string.IsNullOrEmpty(val))
32 | {
33 | return string.Empty;
34 | }
35 |
36 | using (var p = new DESCryptoServiceProvider())
37 | {
38 | p.IV = Default.GetBytes(SecretKey);
39 | p.Key = Default.GetBytes(SecretKey);
40 | using (var ct = p.CreateEncryptor(p.IV, p.Key))
41 | {
42 | var temp = Default.GetBytes(val);
43 | using (var ms = new MemoryStream())
44 | {
45 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
46 | {
47 | await cs.WriteAsync(temp, 0, temp.Length);
48 | await cs.FlushAsync();
49 | cs.Close();
50 | }
51 |
52 | return Convert.ToBase64String(ms.ToArray());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// DES 解密
60 | ///
61 | ///
62 | ///
63 | public static async Task DecryptAsync(this string val)
64 | {
65 | if (string.IsNullOrEmpty(val))
66 | {
67 | return string.Empty;
68 | }
69 |
70 | using (var p = new DESCryptoServiceProvider())
71 | {
72 | p.IV = Default.GetBytes(SecretKey);
73 | p.Key = Default.GetBytes(SecretKey);
74 | using (var ct = p.CreateDecryptor(p.IV, p.Key))
75 | {
76 | val = WebUtility.UrlDecode(val);
77 | val = WebUtility.UrlDecode(val);
78 | var temp = Convert.FromBase64String(val);
79 | using (var ms = new MemoryStream())
80 | {
81 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
82 | {
83 | await cs.WriteAsync(temp, 0, temp.Length);
84 | await cs.FlushAsync();
85 | cs.Close();
86 | }
87 | return Default.GetString(ms.ToArray());
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/Extensions/DesExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CaptchaService.Extensions
9 | {
10 | ///
11 | /// DES加密解密
12 | ///
13 | public static class DesExtension
14 | {
15 | ///
16 | /// 加密密钥
17 | ///
18 | private const string SecretKey = "LOVEROSE";
19 | ///
20 | /// 默认UTF8编码
21 | ///
22 | private static readonly Encoding Default = Encoding.UTF8;
23 |
24 | ///
25 | /// DES 加密
26 | ///
27 | ///
28 | ///
29 | public static async Task EncryptAsync(this string val)
30 | {
31 | if (string.IsNullOrEmpty(val))
32 | {
33 | return string.Empty;
34 | }
35 |
36 | using (var p = new DESCryptoServiceProvider())
37 | {
38 | p.IV = Default.GetBytes(SecretKey);
39 | p.Key = Default.GetBytes(SecretKey);
40 | using (var ct = p.CreateEncryptor(p.IV, p.Key))
41 | {
42 | var temp = Default.GetBytes(val);
43 | using (var ms = new MemoryStream())
44 | {
45 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
46 | {
47 | await cs.WriteAsync(temp, 0, temp.Length);
48 | await cs.FlushAsync();
49 | cs.Close();
50 | }
51 |
52 | return Convert.ToBase64String(ms.ToArray());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// DES 解密
60 | ///
61 | ///
62 | ///
63 | public static async Task DecryptAsync(this string val)
64 | {
65 | if (string.IsNullOrEmpty(val))
66 | {
67 | return string.Empty;
68 | }
69 |
70 | using (var p = new DESCryptoServiceProvider())
71 | {
72 | p.IV = Default.GetBytes(SecretKey);
73 | p.Key = Default.GetBytes(SecretKey);
74 | using (var ct = p.CreateDecryptor(p.IV, p.Key))
75 | {
76 | val = WebUtility.UrlDecode(val);
77 | val = WebUtility.UrlDecode(val);
78 | var temp = Convert.FromBase64String(val);
79 | using (var ms = new MemoryStream())
80 | {
81 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
82 | {
83 | await cs.WriteAsync(temp, 0, temp.Length);
84 | await cs.FlushAsync();
85 | cs.Close();
86 | }
87 | return Default.GetString(ms.ToArray());
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/Extensions/DesExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CaptchaService.Extensions
9 | {
10 | ///
11 | /// DES加密解密
12 | ///
13 | public static class DesExtension
14 | {
15 | ///
16 | /// 加密密钥
17 | ///
18 | private const string SecretKey = "LOVEROSE";
19 | ///
20 | /// 默认UTF8编码
21 | ///
22 | private static readonly Encoding Default = Encoding.UTF8;
23 |
24 | ///
25 | /// DES 加密
26 | ///
27 | ///
28 | ///
29 | public static async Task EncryptAsync(this string val)
30 | {
31 | if (string.IsNullOrEmpty(val))
32 | {
33 | return string.Empty;
34 | }
35 |
36 | using (var p = new DESCryptoServiceProvider())
37 | {
38 | p.IV = Default.GetBytes(SecretKey);
39 | p.Key = Default.GetBytes(SecretKey);
40 | using (var ct = p.CreateEncryptor(p.IV, p.Key))
41 | {
42 | var temp = Default.GetBytes(val);
43 | using (var ms = new MemoryStream())
44 | {
45 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
46 | {
47 | await cs.WriteAsync(temp, 0, temp.Length);
48 | await cs.FlushAsync();
49 | cs.Close();
50 | }
51 |
52 | return Convert.ToBase64String(ms.ToArray());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// DES 解密
60 | ///
61 | ///
62 | ///
63 | public static async Task DecryptAsync(this string val)
64 | {
65 | if (string.IsNullOrEmpty(val))
66 | {
67 | return string.Empty;
68 | }
69 |
70 | using (var p = new DESCryptoServiceProvider())
71 | {
72 | p.IV = Default.GetBytes(SecretKey);
73 | p.Key = Default.GetBytes(SecretKey);
74 | using (var ct = p.CreateDecryptor(p.IV, p.Key))
75 | {
76 | val = WebUtility.UrlDecode(val);
77 | val = WebUtility.UrlDecode(val);
78 | var temp = Convert.FromBase64String(val);
79 | using (var ms = new MemoryStream())
80 | {
81 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
82 | {
83 | await cs.WriteAsync(temp, 0, temp.Length);
84 | await cs.FlushAsync();
85 | cs.Close();
86 | }
87 | return Default.GetString(ms.ToArray());
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/Extensions/DesExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace CaptchaService.Extensions
9 | {
10 | ///
11 | /// DES加密解密
12 | ///
13 | public static class DesExtension
14 | {
15 | ///
16 | /// 加密密钥
17 | ///
18 | private const string SecretKey = "LOVEROSE";
19 | ///
20 | /// 默认UTF8编码
21 | ///
22 | private static readonly Encoding Default = Encoding.UTF8;
23 |
24 | ///
25 | /// DES 加密
26 | ///
27 | ///
28 | ///
29 | public static async Task EncryptAsync(this string val)
30 | {
31 | if (string.IsNullOrEmpty(val))
32 | {
33 | return string.Empty;
34 | }
35 |
36 | using (var p = new DESCryptoServiceProvider())
37 | {
38 | p.IV = Default.GetBytes(SecretKey);
39 | p.Key = Default.GetBytes(SecretKey);
40 | using (var ct = p.CreateEncryptor(p.IV, p.Key))
41 | {
42 | var temp = Default.GetBytes(val);
43 | using (var ms = new MemoryStream())
44 | {
45 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
46 | {
47 | await cs.WriteAsync(temp, 0, temp.Length);
48 | await cs.FlushAsync();
49 | cs.Close();
50 | }
51 |
52 | return Convert.ToBase64String(ms.ToArray());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// DES 解密
60 | ///
61 | ///
62 | ///
63 | public static async Task DecryptAsync(this string val)
64 | {
65 | if (string.IsNullOrEmpty(val))
66 | {
67 | return string.Empty;
68 | }
69 |
70 | using (var p = new DESCryptoServiceProvider())
71 | {
72 | p.IV = Default.GetBytes(SecretKey);
73 | p.Key = Default.GetBytes(SecretKey);
74 | using (var ct = p.CreateDecryptor(p.IV, p.Key))
75 | {
76 | val = WebUtility.UrlDecode(val);
77 | val = WebUtility.UrlDecode(val);
78 | var temp = Convert.FromBase64String(val);
79 | using (var ms = new MemoryStream())
80 | {
81 | using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
82 | {
83 | await cs.WriteAsync(temp, 0, temp.Length);
84 | await cs.FlushAsync();
85 | cs.Close();
86 | }
87 | return Default.GetString(ms.ToArray());
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/captcha.js:
--------------------------------------------------------------------------------
1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2 | return new (P || (P = Promise))(function (resolve, reject) {
3 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
5 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
6 | step((generator = generator.apply(thisArg, _arguments || [])).next());
7 | });
8 | };
9 | var __generator = (this && this.__generator) || function (thisArg, body) {
10 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
11 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12 | function verb(n) { return function (v) { return step([n, v]); }; }
13 | function step(op) {
14 | if (f) throw new TypeError("Generator is already executing.");
15 | while (_) try {
16 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
17 | if (y = 0, t) op = [op[0] & 2, t.value];
18 | switch (op[0]) {
19 | case 0: case 1: t = op; break;
20 | case 4: _.label++; return { value: op[1], done: false };
21 | case 5: _.label++; y = op[1]; op = [0]; continue;
22 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
23 | default:
24 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
25 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
26 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
27 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
28 | if (t[2]) _.ops.pop();
29 | _.trys.pop(); continue;
30 | }
31 | op = body.call(thisArg, _);
32 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
33 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
34 | }
35 | };
36 | var _this = this;
37 | $(document).ready(function () { return __awaiter(_this, void 0, void 0, function () {
38 | var _this = this;
39 | return __generator(this, function (_a) {
40 | $("#btnCaptcha").click(function () { return __awaiter(_this, void 0, void 0, function () {
41 | var answer, captcha, request, result;
42 | return __generator(this, function (_a) {
43 | switch (_a.label) {
44 | case 0:
45 | answer = encodeURI($("#txtCaptcha").val());
46 | captcha = encodeURI(getCookie("Captcha"));
47 | request = {
48 | answer: answer,
49 | captcha: captcha
50 | };
51 | return [4 /*yield*/, verifyAsync(request)];
52 | case 1:
53 | result = _a.sent();
54 | alert("message : " + result.message + ", code : " + result.code);
55 | return [2 /*return*/];
56 | }
57 | });
58 | }); });
59 | return [2 /*return*/];
60 | });
61 | }); });
62 | function verifyAsync(request) {
63 | return __awaiter(this, void 0, void 0, function () {
64 | var url, result;
65 | return __generator(this, function (_a) {
66 | switch (_a.label) {
67 | case 0:
68 | url = "api/captcha/verify";
69 | return [4 /*yield*/, HttpService.instance.postAsync(url, request)];
70 | case 1:
71 | result = _a.sent();
72 | return [2 /*return*/, result];
73 | }
74 | });
75 | });
76 | }
77 | function getCookie(name) {
78 | //获取Cookie值
79 | var strCookie = document.cookie;
80 | var arrCookie = strCookie.split("; ");
81 | for (var i = 0; i < arrCookie.length; i++) {
82 | var arr = arrCookie[i].split("=");
83 | if (arr[0] === name)
84 | return arr[1];
85 | }
86 | return "";
87 | }
88 | //# sourceMappingURL=captcha.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/captcha.js:
--------------------------------------------------------------------------------
1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3 | return new (P || (P = Promise))(function (resolve, reject) {
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
8 | });
9 | };
10 | var __generator = (this && this.__generator) || function (thisArg, body) {
11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13 | function verb(n) { return function (v) { return step([n, v]); }; }
14 | function step(op) {
15 | if (f) throw new TypeError("Generator is already executing.");
16 | while (_) try {
17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18 | if (y = 0, t) op = [op[0] & 2, t.value];
19 | switch (op[0]) {
20 | case 0: case 1: t = op; break;
21 | case 4: _.label++; return { value: op[1], done: false };
22 | case 5: _.label++; y = op[1]; op = [0]; continue;
23 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
24 | default:
25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29 | if (t[2]) _.ops.pop();
30 | _.trys.pop(); continue;
31 | }
32 | op = body.call(thisArg, _);
33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35 | }
36 | };
37 | var _this = this;
38 | $(document).ready(function () { return __awaiter(_this, void 0, void 0, function () {
39 | var _this = this;
40 | return __generator(this, function (_a) {
41 | $("#btnCaptcha").click(function () { return __awaiter(_this, void 0, void 0, function () {
42 | var answer, captcha, request, result;
43 | return __generator(this, function (_a) {
44 | switch (_a.label) {
45 | case 0:
46 | answer = encodeURI($("#txtCaptcha").val());
47 | captcha = encodeURI(getCookie("Captcha"));
48 | request = {
49 | answer: answer,
50 | captcha: captcha
51 | };
52 | return [4 /*yield*/, verifyAsync(request)];
53 | case 1:
54 | result = _a.sent();
55 | alert("message : " + result.message + ", code : " + result.code);
56 | return [2 /*return*/];
57 | }
58 | });
59 | }); });
60 | return [2 /*return*/];
61 | });
62 | }); });
63 | function verifyAsync(request) {
64 | return __awaiter(this, void 0, void 0, function () {
65 | var url, result;
66 | return __generator(this, function (_a) {
67 | switch (_a.label) {
68 | case 0:
69 | url = "api/captcha/verify";
70 | return [4 /*yield*/, HttpService.instance.postAsync(url, request)];
71 | case 1:
72 | result = _a.sent();
73 | return [2 /*return*/, result];
74 | }
75 | });
76 | });
77 | }
78 | function getCookie(name) {
79 | //获取Cookie值
80 | var strCookie = document.cookie;
81 | var arrCookie = strCookie.split("; ");
82 | for (var i = 0; i < arrCookie.length; i++) {
83 | var arr = arrCookie[i].split("=");
84 | if (arr[0] === name)
85 | return arr[1];
86 | }
87 | return "";
88 | }
89 | //# sourceMappingURL=captcha.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/httpService.js:
--------------------------------------------------------------------------------
1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2 | return new (P || (P = Promise))(function (resolve, reject) {
3 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
5 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
6 | step((generator = generator.apply(thisArg, _arguments || [])).next());
7 | });
8 | };
9 | var __generator = (this && this.__generator) || function (thisArg, body) {
10 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
11 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12 | function verb(n) { return function (v) { return step([n, v]); }; }
13 | function step(op) {
14 | if (f) throw new TypeError("Generator is already executing.");
15 | while (_) try {
16 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
17 | if (y = 0, t) op = [op[0] & 2, t.value];
18 | switch (op[0]) {
19 | case 0: case 1: t = op; break;
20 | case 4: _.label++; return { value: op[1], done: false };
21 | case 5: _.label++; y = op[1]; op = [0]; continue;
22 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
23 | default:
24 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
25 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
26 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
27 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
28 | if (t[2]) _.ops.pop();
29 | _.trys.pop(); continue;
30 | }
31 | op = body.call(thisArg, _);
32 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
33 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
34 | }
35 | };
36 | var HttpService = /** @class */ (function () {
37 | function HttpService() {
38 | }
39 | HttpService.prototype.getAsync = function (url) {
40 | return __awaiter(this, void 0, void 0, function () {
41 | var result, e_1;
42 | return __generator(this, function (_a) {
43 | switch (_a.label) {
44 | case 0:
45 | _a.trys.push([0, 2, , 3]);
46 | return [4 /*yield*/, $.ajax(url, { type: "GET" })];
47 | case 1:
48 | result = _a.sent();
49 | return [2 /*return*/, result];
50 | case 2:
51 | e_1 = _a.sent();
52 | alert(e_1);
53 | return [3 /*break*/, 3];
54 | case 3: return [2 /*return*/, null];
55 | }
56 | });
57 | });
58 | };
59 | HttpService.prototype.postAsync = function (url, data) {
60 | return __awaiter(this, void 0, void 0, function () {
61 | var result, e_2;
62 | return __generator(this, function (_a) {
63 | switch (_a.label) {
64 | case 0:
65 | _a.trys.push([0, 2, , 3]);
66 | return [4 /*yield*/, $.ajax({
67 | url: url,
68 | type: "POST",
69 | dataType: "json",
70 | data: JSON.stringify(data),
71 | contentType: 'application/json; charset=utf-8'
72 | })];
73 | case 1:
74 | result = _a.sent();
75 | return [2 /*return*/, result];
76 | case 2:
77 | e_2 = _a.sent();
78 | alert(e_2);
79 | return [3 /*break*/, 3];
80 | case 3: return [2 /*return*/, null];
81 | }
82 | });
83 | });
84 | };
85 | HttpService.instance = new HttpService();
86 | return HttpService;
87 | }());
88 | //# sourceMappingURL=httpService.js.map
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_1_TypeScript/Captcha.WebApi/Captcha.WebApi/wwwroot/js/httpService.js:
--------------------------------------------------------------------------------
1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3 | return new (P || (P = Promise))(function (resolve, reject) {
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
8 | });
9 | };
10 | var __generator = (this && this.__generator) || function (thisArg, body) {
11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13 | function verb(n) { return function (v) { return step([n, v]); }; }
14 | function step(op) {
15 | if (f) throw new TypeError("Generator is already executing.");
16 | while (_) try {
17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18 | if (y = 0, t) op = [op[0] & 2, t.value];
19 | switch (op[0]) {
20 | case 0: case 1: t = op; break;
21 | case 4: _.label++; return { value: op[1], done: false };
22 | case 5: _.label++; y = op[1]; op = [0]; continue;
23 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
24 | default:
25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29 | if (t[2]) _.ops.pop();
30 | _.trys.pop(); continue;
31 | }
32 | op = body.call(thisArg, _);
33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35 | }
36 | };
37 | var HttpService = /** @class */ (function () {
38 | function HttpService() {
39 | }
40 | HttpService.prototype.getAsync = function (url) {
41 | return __awaiter(this, void 0, void 0, function () {
42 | var result, e_1;
43 | return __generator(this, function (_a) {
44 | switch (_a.label) {
45 | case 0:
46 | _a.trys.push([0, 2, , 3]);
47 | return [4 /*yield*/, $.ajax(url, { type: "GET" })];
48 | case 1:
49 | result = _a.sent();
50 | return [2 /*return*/, result];
51 | case 2:
52 | e_1 = _a.sent();
53 | alert(e_1);
54 | return [3 /*break*/, 3];
55 | case 3: return [2 /*return*/, null];
56 | }
57 | });
58 | });
59 | };
60 | HttpService.prototype.postAsync = function (url, data) {
61 | return __awaiter(this, void 0, void 0, function () {
62 | var result, e_2;
63 | return __generator(this, function (_a) {
64 | switch (_a.label) {
65 | case 0:
66 | _a.trys.push([0, 2, , 3]);
67 | return [4 /*yield*/, $.ajax({
68 | url: url,
69 | type: "POST",
70 | dataType: "json",
71 | data: JSON.stringify(data),
72 | contentType: 'application/json; charset=utf-8'
73 | })];
74 | case 1:
75 | result = _a.sent();
76 | return [2 /*return*/, result];
77 | case 2:
78 | e_2 = _a.sent();
79 | alert(e_2);
80 | return [3 /*break*/, 3];
81 | case 3: return [2 /*return*/, null];
82 | }
83 | });
84 | });
85 | };
86 | HttpService.instance = new HttpService();
87 | return HttpService;
88 | }());
89 | //# sourceMappingURL=httpService.js.map
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.pch
68 | *.pdb
69 | *.pgc
70 | *.pgd
71 | *.rsp
72 | *.sbr
73 | *.tlb
74 | *.tli
75 | *.tlh
76 | *.tmp
77 | *.tmp_proj
78 | *.log
79 | *.vspscc
80 | *.vssscc
81 | .builds
82 | *.pidb
83 | *.svclog
84 | *.scc
85 |
86 | # Chutzpah Test files
87 | _Chutzpah*
88 |
89 | # Visual C++ cache files
90 | ipch/
91 | *.aps
92 | *.ncb
93 | *.opendb
94 | *.opensdf
95 | *.sdf
96 | *.cachefile
97 | *.VC.db
98 | *.VC.VC.opendb
99 |
100 | # Visual Studio profiler
101 | *.psess
102 | *.vsp
103 | *.vspx
104 | *.sap
105 |
106 | # Visual Studio Trace Files
107 | *.e2e
108 |
109 | # TFS 2012 Local Workspace
110 | $tf/
111 |
112 | # Guidance Automation Toolkit
113 | *.gpState
114 |
115 | # ReSharper is a .NET coding add-in
116 | _ReSharper*/
117 | *.[Rr]e[Ss]harper
118 | *.DotSettings.user
119 |
120 | # JustCode is a .NET coding add-in
121 | .JustCode
122 |
123 | # TeamCity is a build add-in
124 | _TeamCity*
125 |
126 | # DotCover is a Code Coverage Tool
127 | *.dotCover
128 |
129 | # AxoCover is a Code Coverage Tool
130 | .axoCover/*
131 | !.axoCover/settings.json
132 |
133 | # Visual Studio code coverage results
134 | *.coverage
135 | *.coveragexml
136 |
137 | # NCrunch
138 | _NCrunch_*
139 | .*crunch*.local.xml
140 | nCrunchTemp_*
141 |
142 | # MightyMoose
143 | *.mm.*
144 | AutoTest.Net/
145 |
146 | # Web workbench (sass)
147 | .sass-cache/
148 |
149 | # Installshield output folder
150 | [Ee]xpress/
151 |
152 | # DocProject is a documentation generator add-in
153 | DocProject/buildhelp/
154 | DocProject/Help/*.HxT
155 | DocProject/Help/*.HxC
156 | DocProject/Help/*.hhc
157 | DocProject/Help/*.hhk
158 | DocProject/Help/*.hhp
159 | DocProject/Help/Html2
160 | DocProject/Help/html
161 |
162 | # Click-Once directory
163 | publish/
164 |
165 | # Publish Web Output
166 | *.[Pp]ublish.xml
167 | *.azurePubxml
168 | # Note: Comment the next line if you want to checkin your web deploy settings,
169 | # but database connection strings (with potential passwords) will be unencrypted
170 | *.pubxml
171 | *.publishproj
172 |
173 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
174 | # checkin your Azure Web App publish settings, but sensitive information contained
175 | # in these scripts will be unencrypted
176 | PublishScripts/
177 |
178 | # NuGet Packages
179 | *.nupkg
180 | # The packages folder can be ignored because of Package Restore
181 | **/[Pp]ackages/*
182 | # except build/, which is used as an MSBuild target.
183 | !**/[Pp]ackages/build/
184 | # Uncomment if necessary however generally it will be regenerated when needed
185 | #!**/[Pp]ackages/repositories.config
186 | # NuGet v3's project.json files produces more ignorable files
187 | *.nuget.props
188 | *.nuget.targets
189 |
190 | # Microsoft Azure Build Output
191 | csx/
192 | *.build.csdef
193 |
194 | # Microsoft Azure Emulator
195 | ecf/
196 | rcf/
197 |
198 | # Windows Store app package directories and files
199 | AppPackages/
200 | BundleArtifacts/
201 | Package.StoreAssociation.xml
202 | _pkginfo.txt
203 | *.appx
204 |
205 | # Visual Studio cache files
206 | # files ending in .cache can be ignored
207 | *.[Cc]ache
208 | # but keep track of directories ending in .cache
209 | !*.[Cc]ache/
210 |
211 | # Others
212 | ClientBin/
213 | ~$*
214 | *~
215 | *.dbmdl
216 | *.dbproj.schemaview
217 | *.jfm
218 | *.pfx
219 | *.publishsettings
220 | orleans.codegen.cs
221 |
222 | # Including strong name files can present a security risk
223 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
224 | #*.snk
225 |
226 | # Since there are multiple workflows, uncomment next line to ignore bower_components
227 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
228 | #bower_components/
229 |
230 | # RIA/Silverlight projects
231 | Generated_Code/
232 |
233 | # Backup & report files from converting an old project file
234 | # to a newer Visual Studio version. Backup files are not needed,
235 | # because we have git ;-)
236 | _UpgradeReport_Files/
237 | Backup*/
238 | UpgradeLog*.XML
239 | UpgradeLog*.htm
240 | ServiceFabricBackup/
241 |
242 | # SQL Server files
243 | *.mdf
244 | *.ldf
245 | *.ndf
246 |
247 | # Business Intelligence projects
248 | *.rdl.data
249 | *.bim.layout
250 | *.bim_*.settings
251 | *.rptproj.rsuser
252 |
253 | # Microsoft Fakes
254 | FakesAssemblies/
255 |
256 | # GhostDoc plugin setting file
257 | *.GhostDoc.xml
258 |
259 | # Node.js Tools for Visual Studio
260 | .ntvs_analysis.dat
261 | node_modules/
262 |
263 | # Visual Studio 6 build log
264 | *.plg
265 |
266 | # Visual Studio 6 workspace options file
267 | *.opt
268 |
269 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
270 | *.vbw
271 |
272 | # Visual Studio LightSwitch build output
273 | **/*.HTMLClient/GeneratedArtifacts
274 | **/*.DesktopClient/GeneratedArtifacts
275 | **/*.DesktopClient/ModelManifest.xml
276 | **/*.Server/GeneratedArtifacts
277 | **/*.Server/ModelManifest.xml
278 | _Pvt_Extensions
279 |
280 | # Paket dependency manager
281 | .paket/paket.exe
282 | paket-files/
283 |
284 | # FAKE - F# Make
285 | .fake/
286 |
287 | # JetBrains Rider
288 | .idea/
289 | *.sln.iml
290 |
291 | # CodeRush
292 | .cr/
293 |
294 | # Python Tools for Visual Studio (PTVS)
295 | __pycache__/
296 | *.pyc
297 |
298 | # Cake - Uncomment if you are using it
299 | # tools/**
300 | # !tools/packages.config
301 |
302 | # Tabs Studio
303 | *.tss
304 |
305 | # Telerik's JustMock configuration file
306 | *.jmconfig
307 |
308 | # BizTalk build output
309 | *.btp.cs
310 | *.btm.cs
311 | *.odx.cs
312 | *.xsd.cs
313 |
314 | # OpenCover UI analysis results
315 | OpenCover/
316 |
317 | # Azure Stream Analytics local run output
318 | ASALocalRun/
319 |
320 | # MSBuild Binary and Structured Log
321 | *.binlog
322 |
323 | # NVidia Nsight GPU debugger configuration file
324 | *.nvuser
--------------------------------------------------------------------------------
/WebApi/Captcha/CaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using Captcha.Models;
11 |
12 | namespace Captcha
13 | {
14 | public partial class CaptchaFactory
15 | {
16 | ///
17 | /// 绘制干扰线
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static void Disturb(Random random, Bitmap bitmap, Graphics graphics, int lineCount, int pointCount)
25 | {
26 |
27 | var colors = new List
28 | {
29 | Color.AliceBlue,
30 | Color.Azure,
31 | Color.CadetBlue,
32 | Color.Beige,
33 | Color.Chartreuse
34 | };
35 |
36 | //干扰线
37 | for (var i = 0; i < lineCount; i++)
38 | {
39 | var x1 = random.Next(bitmap.Width);
40 | var x2 = random.Next(bitmap.Width);
41 | var y1 = random.Next(bitmap.Height);
42 | var y2 = random.Next(bitmap.Height);
43 |
44 | //Pen 类 定义用于绘制直线和曲线的对象。
45 | var pen = new Pen(colors[random.Next(0, colors.Count - 1)]);
46 |
47 | graphics.DrawLine(pen, x1, y1, x2, y2);
48 | }
49 |
50 | //干扰点
51 | for (var i = 0; i < pointCount; i++)
52 | {
53 | var x = random.Next(bitmap.Width);
54 | var y = random.Next(bitmap.Height);
55 | bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
56 | }
57 | }
58 | }
59 |
60 | public partial class CaptchaFactory
61 | {
62 | public static CaptchaFactory Intance = new CaptchaFactory();
63 |
64 | private static List _characters;
65 |
66 | private const string ContentType = "image/jpeg";
67 |
68 | public CaptchaFactory()
69 | {
70 | _characters = new List();
71 | //去掉0、o、O
72 | for (var c = '0'; c <= '9'; c++)
73 | {
74 | if (c == '0')
75 | {
76 | continue;
77 | }
78 | _characters.Add(c);
79 | }
80 | for (var c = 'a'; c < 'z'; c++)
81 | {
82 | if (c == 'o')
83 | {
84 | continue;
85 | }
86 | _characters.Add(c);
87 | }
88 | for (var c = 'A'; c < 'Z'; c++)
89 | {
90 | if (c == 'O')
91 | {
92 | continue;
93 | }
94 | _characters.Add(c);
95 | }
96 | }
97 |
98 | public async Task CreateAsync(int charCount = 4, int width = 85, int height = 40)
99 | {
100 | var model = new CaptchaInfo
101 | {
102 | ContentType = ContentType
103 | };
104 |
105 | var chars = new char[charCount];
106 | var len = _characters.Count;
107 | var random = new Random();
108 | for (var i = 0; i < chars.Length; i++)
109 | {
110 | var r = random.Next(len);
111 | chars[i] = _characters[r];
112 | }
113 |
114 | var answer = string.Join(string.Empty, chars);
115 |
116 | model.Answer = await Des.EncryptAsync($"{answer}|{DateTime.Now}");
117 |
118 | //var fontNames = FontFamily.Families.Select(_ => _.Name).ToList();
119 | var fontNames = new List
120 | {
121 | "Helvetica","Arial","Lucida Family","Verdana","Tahoma","Trebuchet MS","Georgia","Times"
122 | };
123 |
124 | //Bitmap 类 封装 GDI+ 包含图形图像和其属性的像素数据的位图。 一个 Bitmap 是用来处理图像像素数据所定义的对象。
125 | //Bitmap 类 继承自 抽象基类 Image 类
126 | using (var bitmap = new Bitmap(width, height))
127 | {
128 | //Graphics 类 封装一个 GDI+ 绘图图面。
129 | using (var graphics = Graphics.FromImage(bitmap))
130 | {
131 | //填充背景色 白色
132 | graphics.Clear(Color.White);
133 |
134 | //绘制干扰线和干扰点
135 | Disturb(random, bitmap, graphics, width / 2, height);
136 |
137 | //添加灰色边框
138 | var pen = new Pen(Color.Silver);
139 | graphics.DrawRectangle(pen, 0, 0, width - 1, height - 1);
140 |
141 | var x = 1;
142 | const int y = 5;
143 |
144 | var rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
145 |
146 | var color = Color.FromArgb(random.Next(100, 122), random.Next(100, 122), random.Next(100, 122));
147 |
148 | foreach (var c in chars)
149 | {
150 | //随机选择字符 字体样式和大小
151 | var fontName = fontNames[random.Next(0, fontNames.Count - 1)];
152 | var font = new Font(fontName, random.Next(15, 20));
153 | //淡化字符颜色
154 | using (var brush = new LinearGradientBrush(rectangle, color, color, 90f, true))
155 | {
156 | brush.SetSigmaBellShape(0.5f);
157 | graphics.DrawString(c.ToString(), font, brush, x + random.Next(-2, 2), y + random.Next(-5, 5));
158 | x = x + width / charCount;
159 | }
160 | }
161 |
162 | using (var memoryStream = new MemoryStream())
163 | {
164 | bitmap.Save(memoryStream, ImageFormat.Jpeg);
165 |
166 | model.Image = memoryStream.ToArray();
167 |
168 | return model;
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
175 | public partial class CaptchaFactory
176 | {
177 | ///
178 | /// 使用线程安全字典,实现验证码只能验证一次的功能,防止机器暴力破解验证码
179 | ///
180 | private static readonly ConcurrentDictionary Dic = new ConcurrentDictionary();
181 |
182 | ///
183 | /// 比对验证码
184 | ///
185 | ///
186 | /// 单位秒,超时时间默认600秒(5分钟)
187 | ///
188 | public async Task VerifyAsync(VerifyRequest model, int timeOut = 600)
189 | {
190 | try
191 | {
192 | //判空
193 | if (string.IsNullOrEmpty(model.Answer) || string.IsNullOrEmpty(model.Captcha))
194 | {
195 | return new VerifyResponse
196 | {
197 | Code = 102,
198 | Message = "验证失败"
199 | };
200 | }
201 |
202 | //一个验证码只能调用一次接口
203 | if (Dic.ContainsKey(model.Captcha))
204 | {
205 | return new VerifyResponse
206 | {
207 | Code = 101,
208 | Message = "验证码失效"
209 | };
210 | }
211 |
212 | //记录第一次调用
213 | Dic.TryAdd(model.Captcha, DateTime.Now);
214 |
215 | //清除垃圾数据
216 | foreach (var d in Dic)
217 | {
218 | var day = (d.Value - DateTime.Now).Days;
219 | if (day > 1)
220 | {
221 | Dic.TryRemove(d.Key, out var date);
222 | }
223 | }
224 |
225 | var captcha = await Des.DecryptAsync(model.Captcha);
226 | var temp = captcha.Split('|');
227 | if (!DateTime.TryParse(temp[1], out var dateTime))
228 | {
229 | return new VerifyResponse
230 | {
231 | Code = 101,
232 | Message = "验证码失效"
233 | };
234 | }
235 |
236 | var sec = (DateTime.Now - dateTime).TotalSeconds;
237 |
238 | if (sec > timeOut)
239 | {
240 | return new VerifyResponse
241 | {
242 | Code = 101,
243 | Message = "验证码失效"
244 | };
245 | }
246 |
247 | var answer = temp[0];
248 | if (string.Equals(answer, model.Answer, StringComparison.CurrentCultureIgnoreCase))
249 | {
250 | return new VerifyResponse
251 | {
252 | Code = 100,
253 | Message = "验证成功"
254 | };
255 | }
256 |
257 | return new VerifyResponse
258 | {
259 | Code = 102,
260 | Message = "验证失败"
261 | };
262 | }
263 | catch (Exception ex)
264 | {
265 | return new VerifyResponse
266 | {
267 | Code = -1,
268 | Message = ex.Message
269 | };
270 | }
271 | }
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/CaptchaService/CaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Threading.Tasks;
9 | using CaptchaService.Extensions;
10 | using CaptchaService.Models;
11 |
12 | namespace CaptchaService
13 | {
14 | public partial class CaptchaFactory : ICaptchaFactory
15 | {
16 | ///
17 | /// 绘制干扰线
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static void Disturb(Random random, Bitmap bitmap, Graphics graphics, int lineCount, int pointCount)
25 | {
26 |
27 | var colors = new List
28 | {
29 | Color.AliceBlue,
30 | Color.Azure,
31 | Color.CadetBlue,
32 | Color.Beige,
33 | Color.Chartreuse
34 | };
35 |
36 | //干扰线
37 | for (var i = 0; i < lineCount; i++)
38 | {
39 | var x1 = random.Next(bitmap.Width);
40 | var x2 = random.Next(bitmap.Width);
41 | var y1 = random.Next(bitmap.Height);
42 | var y2 = random.Next(bitmap.Height);
43 |
44 | //Pen 类 定义用于绘制直线和曲线的对象。
45 | var pen = new Pen(colors[random.Next(0, colors.Count - 1)]);
46 |
47 | graphics.DrawLine(pen, x1, y1, x2, y2);
48 | }
49 |
50 | //干扰点
51 | for (var i = 0; i < pointCount; i++)
52 | {
53 | var x = random.Next(bitmap.Width);
54 | var y = random.Next(bitmap.Height);
55 | bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
56 | }
57 | }
58 | }
59 |
60 | public partial class CaptchaFactory
61 | {
62 | private static List _characters;
63 |
64 | private const string ContentType = "image/jpeg";
65 |
66 | public CaptchaFactory()
67 | {
68 | _characters = new List();
69 | //去掉0、o、O
70 | for (var c = '0'; c <= '9'; c++)
71 | {
72 | if (c == '0')
73 | {
74 | continue;
75 | }
76 | _characters.Add(c);
77 | }
78 | for (var c = 'a'; c < 'z'; c++)
79 | {
80 | if (c == 'o')
81 | {
82 | continue;
83 | }
84 | _characters.Add(c);
85 | }
86 | for (var c = 'A'; c < 'Z'; c++)
87 | {
88 | if (c == 'O')
89 | {
90 | continue;
91 | }
92 | _characters.Add(c);
93 | }
94 | }
95 |
96 | public async Task CreateAsync(int charCount = 4, int width = 85, int height = 40)
97 | {
98 | var model = new CaptchaInfo
99 | {
100 | ContentType = ContentType
101 | };
102 |
103 | var chars = new char[charCount];
104 | var len = _characters.Count;
105 | var random = new Random();
106 | for (var i = 0; i < chars.Length; i++)
107 | {
108 | var r = random.Next(len);
109 | chars[i] = _characters[r];
110 | }
111 |
112 | var answer = string.Join(string.Empty, chars);
113 |
114 | //Des加密
115 | var input = $"{answer}|{DateTime.Now}";
116 | model.Answer = await input.EncryptAsync();
117 |
118 | //var fontNames = FontFamily.Families.Select(_ => _.Name).ToList();
119 | var fontNames = new List
120 | {
121 | "Helvetica","Arial","Lucida Family","Verdana","Tahoma","Trebuchet MS","Georgia","Times"
122 | };
123 |
124 | //Bitmap 类 封装 GDI+ 包含图形图像和其属性的像素数据的位图。 一个 Bitmap 是用来处理图像像素数据所定义的对象。
125 | //Bitmap 类 继承自 抽象基类 Image 类
126 | using (var bitmap = new Bitmap(width, height))
127 | {
128 | //Graphics 类 封装一个 GDI+ 绘图图面。
129 | using (var graphics = Graphics.FromImage(bitmap))
130 | {
131 | //填充背景色 白色
132 | graphics.Clear(Color.White);
133 |
134 | //绘制干扰线和干扰点
135 | Disturb(random, bitmap, graphics, width / 2, height);
136 |
137 | //添加灰色边框
138 | var pen = new Pen(Color.Silver);
139 | graphics.DrawRectangle(pen, 0, 0, width - 1, height - 1);
140 |
141 | var x = 1;
142 | const int y = 5;
143 |
144 | var rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
145 |
146 | var color = Color.FromArgb(random.Next(100, 122), random.Next(100, 122), random.Next(100, 122));
147 |
148 | foreach (var c in chars)
149 | {
150 | //随机选择字符 字体样式和大小
151 | var fontName = fontNames[random.Next(0, fontNames.Count - 1)];
152 | var font = new Font(fontName, random.Next(15, 20));
153 | //淡化字符颜色
154 | using (var brush = new LinearGradientBrush(rectangle, color, color, 90f, true))
155 | {
156 | brush.SetSigmaBellShape(0.5f);
157 | graphics.DrawString(c.ToString(), font, brush, x + random.Next(-2, 2), y + random.Next(-5, 5));
158 | x = x + width / charCount;
159 | }
160 | }
161 |
162 | using (var memoryStream = new MemoryStream())
163 | {
164 | bitmap.Save(memoryStream, ImageFormat.Jpeg);
165 |
166 | model.Image = memoryStream.ToArray();
167 |
168 | return model;
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
175 | public partial class CaptchaFactory
176 | {
177 | ///
178 | /// 使用线程安全字典,实现验证码只能验证一次的功能,防止机器暴力破解验证码
179 | ///
180 | private static readonly ConcurrentDictionary Dic = new ConcurrentDictionary();
181 |
182 | ///
183 | /// 比对验证码
184 | ///
185 | ///
186 | /// 单位秒,超时时间默认600秒(5分钟)
187 | ///
188 | public async Task VerifyAsync(VerifyRequest model, int timeOut = 600)
189 | {
190 | try
191 | {
192 | //判空
193 | if (string.IsNullOrEmpty(model.Answer) || string.IsNullOrEmpty(model.Captcha))
194 | {
195 | return new VerifyResponse
196 | {
197 | Code = 102,
198 | Message = "验证失败"
199 | };
200 | }
201 |
202 | //一个验证码只能调用一次接口
203 | if (Dic.ContainsKey(model.Captcha))
204 | {
205 | return new VerifyResponse
206 | {
207 | Code = 101,
208 | Message = "验证码失效"
209 | };
210 | }
211 |
212 | //记录第一次调用
213 | Dic.TryAdd(model.Captcha, DateTime.Now);
214 |
215 | //清除垃圾数据
216 | foreach (var d in Dic)
217 | {
218 | var day = (d.Value - DateTime.Now).Days;
219 | if (day > 1)
220 | {
221 | Dic.TryRemove(d.Key, out var date);
222 | }
223 | }
224 |
225 | //Des解密
226 | var captcha = await model.Captcha.DecryptAsync();
227 | var temp = captcha.Split('|');
228 | if (!DateTime.TryParse(temp[1], out var dateTime))
229 | {
230 | return new VerifyResponse
231 | {
232 | Code = 101,
233 | Message = "验证码失效"
234 | };
235 | }
236 |
237 | var sec = (DateTime.Now - dateTime).TotalSeconds;
238 |
239 | if (sec > timeOut)
240 | {
241 | return new VerifyResponse
242 | {
243 | Code = 101,
244 | Message = "验证码失效"
245 | };
246 | }
247 |
248 | var answer = temp[0];
249 | if (string.Equals(answer, model.Answer, StringComparison.CurrentCultureIgnoreCase))
250 | {
251 | return new VerifyResponse
252 | {
253 | Code = 100,
254 | Message = "验证成功"
255 | };
256 | }
257 |
258 | return new VerifyResponse
259 | {
260 | Code = 102,
261 | Message = "验证失败"
262 | };
263 | }
264 | catch (Exception ex)
265 | {
266 | return new VerifyResponse
267 | {
268 | Code = -1,
269 | Message = ex.Message
270 | };
271 | }
272 | }
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2/Captcha.WebApi/CaptchaService/CaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Threading.Tasks;
9 | using CaptchaService.Extensions;
10 | using CaptchaService.Models;
11 |
12 | namespace CaptchaService
13 | {
14 | public partial class CaptchaFactory : ICaptchaFactory
15 | {
16 | ///
17 | /// 绘制干扰线
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static void Disturb(Random random, Bitmap bitmap, Graphics graphics, int lineCount, int pointCount)
25 | {
26 |
27 | var colors = new List
28 | {
29 | Color.AliceBlue,
30 | Color.Azure,
31 | Color.CadetBlue,
32 | Color.Beige,
33 | Color.Chartreuse
34 | };
35 |
36 | //干扰线
37 | for (var i = 0; i < lineCount; i++)
38 | {
39 | var x1 = random.Next(bitmap.Width);
40 | var x2 = random.Next(bitmap.Width);
41 | var y1 = random.Next(bitmap.Height);
42 | var y2 = random.Next(bitmap.Height);
43 |
44 | //Pen 类 定义用于绘制直线和曲线的对象。
45 | var pen = new Pen(colors[random.Next(0, colors.Count - 1)]);
46 |
47 | graphics.DrawLine(pen, x1, y1, x2, y2);
48 | }
49 |
50 | //干扰点
51 | for (var i = 0; i < pointCount; i++)
52 | {
53 | var x = random.Next(bitmap.Width);
54 | var y = random.Next(bitmap.Height);
55 | bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
56 | }
57 | }
58 | }
59 |
60 | public partial class CaptchaFactory
61 | {
62 | private static List _characters;
63 |
64 | private const string ContentType = "image/jpeg";
65 |
66 | public CaptchaFactory()
67 | {
68 | _characters = new List();
69 | //去掉0、o、O
70 | for (var c = '0'; c <= '9'; c++)
71 | {
72 | if (c == '0')
73 | {
74 | continue;
75 | }
76 | _characters.Add(c);
77 | }
78 | for (var c = 'a'; c < 'z'; c++)
79 | {
80 | if (c == 'o')
81 | {
82 | continue;
83 | }
84 | _characters.Add(c);
85 | }
86 | for (var c = 'A'; c < 'Z'; c++)
87 | {
88 | if (c == 'O')
89 | {
90 | continue;
91 | }
92 | _characters.Add(c);
93 | }
94 | }
95 |
96 | public async Task CreateAsync(int charCount = 4, int width = 85, int height = 40)
97 | {
98 | var model = new CaptchaInfo
99 | {
100 | ContentType = ContentType
101 | };
102 |
103 | var chars = new char[charCount];
104 | var len = _characters.Count;
105 | var random = new Random();
106 | for (var i = 0; i < chars.Length; i++)
107 | {
108 | var r = random.Next(len);
109 | chars[i] = _characters[r];
110 | }
111 |
112 | var answer = string.Join(string.Empty, chars);
113 |
114 | //Des加密
115 | var input = $"{answer}|{DateTime.Now}";
116 | model.Answer = await input.EncryptAsync();
117 |
118 | //var fontNames = FontFamily.Families.Select(_ => _.Name).ToList();
119 | var fontNames = new List
120 | {
121 | "Helvetica","Arial","Lucida Family","Verdana","Tahoma","Trebuchet MS","Georgia","Times"
122 | };
123 |
124 | //Bitmap 类 封装 GDI+ 包含图形图像和其属性的像素数据的位图。 一个 Bitmap 是用来处理图像像素数据所定义的对象。
125 | //Bitmap 类 继承自 抽象基类 Image 类
126 | using (var bitmap = new Bitmap(width, height))
127 | {
128 | //Graphics 类 封装一个 GDI+ 绘图图面。
129 | using (var graphics = Graphics.FromImage(bitmap))
130 | {
131 | //填充背景色 白色
132 | graphics.Clear(Color.White);
133 |
134 | //绘制干扰线和干扰点
135 | Disturb(random, bitmap, graphics, width / 2, height);
136 |
137 | //添加灰色边框
138 | var pen = new Pen(Color.Silver);
139 | graphics.DrawRectangle(pen, 0, 0, width - 1, height - 1);
140 |
141 | var x = 1;
142 | const int y = 5;
143 |
144 | var rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
145 |
146 | var color = Color.FromArgb(random.Next(100, 122), random.Next(100, 122), random.Next(100, 122));
147 |
148 | foreach (var c in chars)
149 | {
150 | //随机选择字符 字体样式和大小
151 | var fontName = fontNames[random.Next(0, fontNames.Count - 1)];
152 | var font = new Font(fontName, random.Next(15, 20));
153 | //淡化字符颜色
154 | using (var brush = new LinearGradientBrush(rectangle, color, color, 90f, true))
155 | {
156 | brush.SetSigmaBellShape(0.5f);
157 | graphics.DrawString(c.ToString(), font, brush, x + random.Next(-2, 2), y + random.Next(-5, 5));
158 | x = x + width / charCount;
159 | }
160 | }
161 |
162 | using (var memoryStream = new MemoryStream())
163 | {
164 | bitmap.Save(memoryStream, ImageFormat.Jpeg);
165 |
166 | model.Image = memoryStream.ToArray();
167 |
168 | return model;
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
175 | public partial class CaptchaFactory
176 | {
177 | ///
178 | /// 使用线程安全字典,实现验证码只能验证一次的功能,防止机器暴力破解验证码
179 | ///
180 | private static readonly ConcurrentDictionary Dic = new ConcurrentDictionary();
181 |
182 | ///
183 | /// 比对验证码
184 | ///
185 | ///
186 | /// 单位秒,超时时间默认600秒(5分钟)
187 | ///
188 | public async Task VerifyAsync(VerifyRequest model, int timeOut = 600)
189 | {
190 | try
191 | {
192 | //判空
193 | if (string.IsNullOrEmpty(model.Answer) || string.IsNullOrEmpty(model.Captcha))
194 | {
195 | return new VerifyResponse
196 | {
197 | Code = 102,
198 | Message = "验证失败"
199 | };
200 | }
201 |
202 | //一个验证码只能调用一次接口
203 | if (Dic.ContainsKey(model.Captcha))
204 | {
205 | return new VerifyResponse
206 | {
207 | Code = 101,
208 | Message = "验证码失效"
209 | };
210 | }
211 |
212 | //记录第一次调用
213 | Dic.TryAdd(model.Captcha, DateTime.Now);
214 |
215 | //清除垃圾数据
216 | foreach (var d in Dic)
217 | {
218 | var day = (d.Value - DateTime.Now).Days;
219 | if (day > 1)
220 | {
221 | Dic.TryRemove(d.Key, out var date);
222 | }
223 | }
224 |
225 | //Des解密
226 | var captcha = await model.Captcha.DecryptAsync();
227 | var temp = captcha.Split('|');
228 | if (!DateTime.TryParse(temp[1], out var dateTime))
229 | {
230 | return new VerifyResponse
231 | {
232 | Code = 101,
233 | Message = "验证码失效"
234 | };
235 | }
236 |
237 | var sec = (DateTime.Now - dateTime).TotalSeconds;
238 |
239 | if (sec > timeOut)
240 | {
241 | return new VerifyResponse
242 | {
243 | Code = 101,
244 | Message = "验证码失效"
245 | };
246 | }
247 |
248 | var answer = temp[0];
249 | if (string.Equals(answer, model.Answer, StringComparison.CurrentCultureIgnoreCase))
250 | {
251 | return new VerifyResponse
252 | {
253 | Code = 100,
254 | Message = "验证成功"
255 | };
256 | }
257 |
258 | return new VerifyResponse
259 | {
260 | Code = 102,
261 | Message = "验证失败"
262 | };
263 | }
264 | catch (Exception ex)
265 | {
266 | return new VerifyResponse
267 | {
268 | Code = -1,
269 | Message = ex.Message
270 | };
271 | }
272 | }
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore2_2_TypeScript/Captcha.WebApi/CaptchaService/CaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Threading.Tasks;
9 | using CaptchaService.Extensions;
10 | using CaptchaService.Models;
11 |
12 | namespace CaptchaService
13 | {
14 | public partial class CaptchaFactory : ICaptchaFactory
15 | {
16 | ///
17 | /// 绘制干扰线
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static void Disturb(Random random, Bitmap bitmap, Graphics graphics, int lineCount, int pointCount)
25 | {
26 |
27 | var colors = new List
28 | {
29 | Color.AliceBlue,
30 | Color.Azure,
31 | Color.CadetBlue,
32 | Color.Beige,
33 | Color.Chartreuse
34 | };
35 |
36 | //干扰线
37 | for (var i = 0; i < lineCount; i++)
38 | {
39 | var x1 = random.Next(bitmap.Width);
40 | var x2 = random.Next(bitmap.Width);
41 | var y1 = random.Next(bitmap.Height);
42 | var y2 = random.Next(bitmap.Height);
43 |
44 | //Pen 类 定义用于绘制直线和曲线的对象。
45 | var pen = new Pen(colors[random.Next(0, colors.Count - 1)]);
46 |
47 | graphics.DrawLine(pen, x1, y1, x2, y2);
48 | }
49 |
50 | //干扰点
51 | for (var i = 0; i < pointCount; i++)
52 | {
53 | var x = random.Next(bitmap.Width);
54 | var y = random.Next(bitmap.Height);
55 | bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
56 | }
57 | }
58 | }
59 |
60 | public partial class CaptchaFactory
61 | {
62 | private static List _characters;
63 |
64 | private const string ContentType = "image/jpeg";
65 |
66 | public CaptchaFactory()
67 | {
68 | _characters = new List();
69 | //去掉0、o、O
70 | for (var c = '0'; c <= '9'; c++)
71 | {
72 | if (c == '0')
73 | {
74 | continue;
75 | }
76 | _characters.Add(c);
77 | }
78 | for (var c = 'a'; c < 'z'; c++)
79 | {
80 | if (c == 'o')
81 | {
82 | continue;
83 | }
84 | _characters.Add(c);
85 | }
86 | for (var c = 'A'; c < 'Z'; c++)
87 | {
88 | if (c == 'O')
89 | {
90 | continue;
91 | }
92 | _characters.Add(c);
93 | }
94 | }
95 |
96 | public async Task CreateAsync(int charCount = 4, int width = 85, int height = 40)
97 | {
98 | var model = new CaptchaInfo
99 | {
100 | ContentType = ContentType
101 | };
102 |
103 | var chars = new char[charCount];
104 | var len = _characters.Count;
105 | var random = new Random();
106 | for (var i = 0; i < chars.Length; i++)
107 | {
108 | var r = random.Next(len);
109 | chars[i] = _characters[r];
110 | }
111 |
112 | var answer = string.Join(string.Empty, chars);
113 |
114 | //Des加密
115 | var input = $"{answer}|{DateTime.Now}";
116 | model.Answer = await input.EncryptAsync();
117 |
118 | //var fontNames = FontFamily.Families.Select(_ => _.Name).ToList();
119 | var fontNames = new List
120 | {
121 | "Helvetica","Arial","Lucida Family","Verdana","Tahoma","Trebuchet MS","Georgia","Times"
122 | };
123 |
124 | //Bitmap 类 封装 GDI+ 包含图形图像和其属性的像素数据的位图。 一个 Bitmap 是用来处理图像像素数据所定义的对象。
125 | //Bitmap 类 继承自 抽象基类 Image 类
126 | using (var bitmap = new Bitmap(width, height))
127 | {
128 | //Graphics 类 封装一个 GDI+ 绘图图面。
129 | using (var graphics = Graphics.FromImage(bitmap))
130 | {
131 | //填充背景色 白色
132 | graphics.Clear(Color.White);
133 |
134 | //绘制干扰线和干扰点
135 | Disturb(random, bitmap, graphics, width / 2, height);
136 |
137 | //添加灰色边框
138 | var pen = new Pen(Color.Silver);
139 | graphics.DrawRectangle(pen, 0, 0, width - 1, height - 1);
140 |
141 | var x = 1;
142 | const int y = 5;
143 |
144 | var rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
145 |
146 | var color = Color.FromArgb(random.Next(100, 122), random.Next(100, 122), random.Next(100, 122));
147 |
148 | foreach (var c in chars)
149 | {
150 | //随机选择字符 字体样式和大小
151 | var fontName = fontNames[random.Next(0, fontNames.Count - 1)];
152 | var font = new Font(fontName, random.Next(15, 20));
153 | //淡化字符颜色
154 | using (var brush = new LinearGradientBrush(rectangle, color, color, 90f, true))
155 | {
156 | brush.SetSigmaBellShape(0.5f);
157 | graphics.DrawString(c.ToString(), font, brush, x + random.Next(-2, 2), y + random.Next(-5, 5));
158 | x = x + width / charCount;
159 | }
160 | }
161 |
162 | using (var memoryStream = new MemoryStream())
163 | {
164 | bitmap.Save(memoryStream, ImageFormat.Jpeg);
165 |
166 | model.Image = memoryStream.ToArray();
167 |
168 | return model;
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
175 | public partial class CaptchaFactory
176 | {
177 | ///
178 | /// 使用线程安全字典,实现验证码只能验证一次的功能,防止机器暴力破解验证码
179 | ///
180 | private static readonly ConcurrentDictionary Dic = new ConcurrentDictionary();
181 |
182 | ///
183 | /// 比对验证码
184 | ///
185 | ///
186 | /// 单位秒,超时时间默认600秒(5分钟)
187 | ///
188 | public async Task VerifyAsync(VerifyRequest model, int timeOut = 600)
189 | {
190 | try
191 | {
192 | //判空
193 | if (string.IsNullOrEmpty(model.Answer) || string.IsNullOrEmpty(model.Captcha))
194 | {
195 | return new VerifyResponse
196 | {
197 | Code = 102,
198 | Message = "验证失败"
199 | };
200 | }
201 |
202 | //一个验证码只能调用一次接口
203 | if (Dic.ContainsKey(model.Captcha))
204 | {
205 | return new VerifyResponse
206 | {
207 | Code = 101,
208 | Message = "验证码失效"
209 | };
210 | }
211 |
212 | //记录第一次调用
213 | Dic.TryAdd(model.Captcha, DateTime.Now);
214 |
215 | //清除垃圾数据
216 | foreach (var d in Dic)
217 | {
218 | var day = (d.Value - DateTime.Now).Days;
219 | if (day > 1)
220 | {
221 | Dic.TryRemove(d.Key, out var date);
222 | }
223 | }
224 |
225 | //Des解密
226 | var captcha = await model.Captcha.DecryptAsync();
227 | var temp = captcha.Split('|');
228 | if (!DateTime.TryParse(temp[1], out var dateTime))
229 | {
230 | return new VerifyResponse
231 | {
232 | Code = 101,
233 | Message = "验证码失效"
234 | };
235 | }
236 |
237 | var sec = (DateTime.Now - dateTime).TotalSeconds;
238 |
239 | if (sec > timeOut)
240 | {
241 | return new VerifyResponse
242 | {
243 | Code = 101,
244 | Message = "验证码失效"
245 | };
246 | }
247 |
248 | var answer = temp[0];
249 | if (string.Equals(answer, model.Answer, StringComparison.CurrentCultureIgnoreCase))
250 | {
251 | return new VerifyResponse
252 | {
253 | Code = 100,
254 | Message = "验证成功"
255 | };
256 | }
257 |
258 | return new VerifyResponse
259 | {
260 | Code = 102,
261 | Message = "验证失败"
262 | };
263 | }
264 | catch (Exception ex)
265 | {
266 | return new VerifyResponse
267 | {
268 | Code = -1,
269 | Message = ex.Message
270 | };
271 | }
272 | }
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/WebApi_AspDotNetCore3_0_TypeScript/Captcha.WebApi/CaptchaService/CaptchaFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Drawing;
5 | using System.Drawing.Drawing2D;
6 | using System.Drawing.Imaging;
7 | using System.IO;
8 | using System.Threading.Tasks;
9 | using CaptchaService.Extensions;
10 | using CaptchaService.Models;
11 |
12 | namespace CaptchaService
13 | {
14 | public partial class CaptchaFactory : ICaptchaFactory
15 | {
16 | ///
17 | /// 绘制干扰线
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static void Disturb(Random random, Bitmap bitmap, Graphics graphics, int lineCount, int pointCount)
25 | {
26 |
27 | var colors = new List
28 | {
29 | Color.AliceBlue,
30 | Color.Azure,
31 | Color.CadetBlue,
32 | Color.Beige,
33 | Color.Chartreuse
34 | };
35 |
36 | //干扰线
37 | for (var i = 0; i < lineCount; i++)
38 | {
39 | var x1 = random.Next(bitmap.Width);
40 | var x2 = random.Next(bitmap.Width);
41 | var y1 = random.Next(bitmap.Height);
42 | var y2 = random.Next(bitmap.Height);
43 |
44 | //Pen 类 定义用于绘制直线和曲线的对象。
45 | var pen = new Pen(colors[random.Next(0, colors.Count - 1)]);
46 |
47 | graphics.DrawLine(pen, x1, y1, x2, y2);
48 | }
49 |
50 | //干扰点
51 | for (var i = 0; i < pointCount; i++)
52 | {
53 | var x = random.Next(bitmap.Width);
54 | var y = random.Next(bitmap.Height);
55 | bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
56 | }
57 | }
58 | }
59 |
60 | public partial class CaptchaFactory
61 | {
62 | private static List _characters;
63 |
64 | private const string ContentType = "image/jpeg";
65 |
66 | public CaptchaFactory()
67 | {
68 | _characters = new List();
69 | //去掉0、o、O
70 | for (var c = '0'; c <= '9'; c++)
71 | {
72 | if (c == '0')
73 | {
74 | continue;
75 | }
76 | _characters.Add(c);
77 | }
78 | for (var c = 'a'; c < 'z'; c++)
79 | {
80 | if (c == 'o')
81 | {
82 | continue;
83 | }
84 | _characters.Add(c);
85 | }
86 | for (var c = 'A'; c < 'Z'; c++)
87 | {
88 | if (c == 'O')
89 | {
90 | continue;
91 | }
92 | _characters.Add(c);
93 | }
94 | }
95 |
96 | public async Task CreateAsync(int charCount = 4, int width = 85, int height = 40)
97 | {
98 | var model = new CaptchaInfo
99 | {
100 | ContentType = ContentType
101 | };
102 |
103 | var chars = new char[charCount];
104 | var len = _characters.Count;
105 | var random = new Random();
106 | for (var i = 0; i < chars.Length; i++)
107 | {
108 | var r = random.Next(len);
109 | chars[i] = _characters[r];
110 | }
111 |
112 | var answer = string.Join(string.Empty, chars);
113 |
114 | //Des加密
115 | var input = $"{answer}|{DateTime.Now}";
116 | model.Answer = await input.EncryptAsync();
117 |
118 | //var fontNames = FontFamily.Families.Select(_ => _.Name).ToList();
119 | var fontNames = new List
120 | {
121 | "Helvetica","Arial","Lucida Family","Verdana","Tahoma","Trebuchet MS","Georgia","Times"
122 | };
123 |
124 | //Bitmap 类 封装 GDI+ 包含图形图像和其属性的像素数据的位图。 一个 Bitmap 是用来处理图像像素数据所定义的对象。
125 | //Bitmap 类 继承自 抽象基类 Image 类
126 | using (var bitmap = new Bitmap(width, height))
127 | {
128 | //Graphics 类 封装一个 GDI+ 绘图图面。
129 | using (var graphics = Graphics.FromImage(bitmap))
130 | {
131 | //填充背景色 白色
132 | graphics.Clear(Color.White);
133 |
134 | //绘制干扰线和干扰点
135 | Disturb(random, bitmap, graphics, width / 2, height);
136 |
137 | //添加灰色边框
138 | var pen = new Pen(Color.Silver);
139 | graphics.DrawRectangle(pen, 0, 0, width - 1, height - 1);
140 |
141 | var x = 1;
142 | const int y = 5;
143 |
144 | var rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
145 |
146 | var color = Color.FromArgb(random.Next(100, 122), random.Next(100, 122), random.Next(100, 122));
147 |
148 | foreach (var c in chars)
149 | {
150 | //随机选择字符 字体样式和大小
151 | var fontName = fontNames[random.Next(0, fontNames.Count - 1)];
152 | var font = new Font(fontName, random.Next(15, 20));
153 | //淡化字符颜色
154 | using (var brush = new LinearGradientBrush(rectangle, color, color, 90f, true))
155 | {
156 | brush.SetSigmaBellShape(0.5f);
157 | graphics.DrawString(c.ToString(), font, brush, x + random.Next(-2, 2), y + random.Next(-5, 5));
158 | x = x + width / charCount;
159 | }
160 | }
161 |
162 | using (var memoryStream = new MemoryStream())
163 | {
164 | bitmap.Save(memoryStream, ImageFormat.Jpeg);
165 |
166 | model.Image = memoryStream.ToArray();
167 |
168 | return model;
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
175 | public partial class CaptchaFactory
176 | {
177 | ///
178 | /// 使用线程安全字典,实现验证码只能验证一次的功能,防止机器暴力破解验证码
179 | ///
180 | private static readonly ConcurrentDictionary Dic = new ConcurrentDictionary();
181 |
182 | ///
183 | /// 比对验证码
184 | ///
185 | ///
186 | /// 单位秒,超时时间默认600秒(5分钟)
187 | ///
188 | public async Task VerifyAsync(VerifyRequest model, int timeOut = 600)
189 | {
190 | try
191 | {
192 | //判空
193 | if (string.IsNullOrEmpty(model.Answer) || string.IsNullOrEmpty(model.Captcha))
194 | {
195 | return new VerifyResponse
196 | {
197 | Code = 102,
198 | Message = "验证失败"
199 | };
200 | }
201 |
202 | //一个验证码只能调用一次接口
203 | if (Dic.ContainsKey(model.Captcha))
204 | {
205 | return new VerifyResponse
206 | {
207 | Code = 101,
208 | Message = "验证码失效"
209 | };
210 | }
211 |
212 | //记录第一次调用
213 | Dic.TryAdd(model.Captcha, DateTime.Now);
214 |
215 | //清除垃圾数据
216 | foreach (var d in Dic)
217 | {
218 | var day = (d.Value - DateTime.Now).Days;
219 | if (day > 1)
220 | {
221 | Dic.TryRemove(d.Key, out var date);
222 | }
223 | }
224 |
225 | //Des解密
226 | var captcha = await model.Captcha.DecryptAsync();
227 | var temp = captcha.Split('|');
228 | if (!DateTime.TryParse(temp[1], out var dateTime))
229 | {
230 | return new VerifyResponse
231 | {
232 | Code = 101,
233 | Message = "验证码失效"
234 | };
235 | }
236 |
237 | var sec = (DateTime.Now - dateTime).TotalSeconds;
238 |
239 | if (sec > timeOut)
240 | {
241 | return new VerifyResponse
242 | {
243 | Code = 101,
244 | Message = "验证码失效"
245 | };
246 | }
247 |
248 | var answer = temp[0];
249 | if (string.Equals(answer, model.Answer, StringComparison.CurrentCultureIgnoreCase))
250 | {
251 | return new VerifyResponse
252 | {
253 | Code = 100,
254 | Message = "验证成功"
255 | };
256 | }
257 |
258 | return new VerifyResponse
259 | {
260 | Code = 102,
261 | Message = "验证失败"
262 | };
263 | }
264 | catch (Exception ex)
265 | {
266 | return new VerifyResponse
267 | {
268 | Code = -1,
269 | Message = ex.Message
270 | };
271 | }
272 | }
273 | }
274 | }
275 |
--------------------------------------------------------------------------------