如何在ASP.NET Web API应用程序中集成ApiFrame
关于如何将 ApiFrame 集成到 Web API 应用程序中的指南。
引言
本文将提供关于如何将ApiFrame集成到ASP.NET Web API项目的一些指导。ApiFrame是一个简单的.NET库,为实现Web API安全(HMAC认证)、异常处理和Web API方法版本控制提供支持。该库就像一个插件组件,您可以轻松地将其集成到您的应用程序中。您可以在此CodeProject文章中找到ApiFrame的源代码和相关信息。
ApiFrame:一个用于Web API安全、异常和版本控制的简单库[^]
我将带领您了解一个简单的Web API示例应用程序,该应用程序实现了POST和GET方法,用于演示认证、授权、版本控制和异常处理。此外,我将向您介绍如何从API客户端消费该服务。
指南:如何在Web API项目中集成API Frame
首先,让我们创建一个示例应用程序。
- 打开Visual Studio 2012
- 创建一个新的ASP.NET MVC 4 Web应用程序
- 选择Web API项目模板
安装
要安装ApiFrame,请在包管理器控制台中运行以下命令

或者,可以通过Nuget包管理器在项目中引用该库。在解决方案资源管理器中,选择Web API项目 -> 右键单击并打开“管理Nuget包…” -> 在线搜索“ApiFrame”。您将看到以下结果,点击安装按钮,这将把API frame添加到您的项目中。
配置
如果您通过ApiFrame实现认证和授权,那么需要在您的应用程序中实现以下接口。
- IApiInception
为了演示目的,让我们在Web API项目中执行以下操作
- 创建一个名为“ApiFrameConfig”的新文件夹
- 在新文件夹内部
- 创建一个实现“IApiInception”的类“ApiInception”
- 创建一个实现“IApiException”的类“ApiException”
实现IApiInception

此接口暴露了三个方法。您项目中GetApplicationToken()的实现取决于您的业务模型。如果您将API服务暴露给多个客户,则每个客户都需要有一个访问令牌和秘密令牌。通常,访问令牌和秘密令牌在注册时创建,并与客户共享,以便客户端应用程序与服务进行通信。如果服务暴露给单个客户,则此配置可以添加到Web.config文件中。AuthScheme是授权方案,这可以是一个您保留在Web.Config中的通用标签,或者如果您想为每个客户附加一个缩写名称,则可以使用此属性。这取决于您的选择,但此信息也由库进行验证。因此,AuthScheme是您需要与客户端共享的另一个信息。
为了演示目的,我在我的示例中进行了以下实现。
public ApiApplicationToken GetApplicationToken(string accessToken)
{
return new ApiApplicationToken()
{
AuthScheme = "HMAC",
AccessToken = "d85aa01c-cf92-4f1e-9862-638fa4ae37b4",
SecretToken = "06fb3823-b8cc-462b-b855-f655d49eb3e2"
};
}
认证基于用户名和密码。理想情况下,您项目中的以下方法将调用服务/数据访问层来检查给定的用户名和密码是否有效。为了实现此方法,应为每个现有用户附加一个访问令牌和秘密令牌。如果用户名和密码有效,则该方法应返回一个用户令牌,如以下代码示例所示。这些用户令牌用于授权目的。客户端应用程序可以保留这些令牌,并使用它们发出后续请求以访问授权资源。ApiFrame还支持基于角色的访问。如果您的应用程序不使用基于角色的访问,则Role属性可以为空。
以下代码仅用于演示目的。
public ApiUserToken GetUserToken(string username, string password)
{
if (username == "demo" && password == "demo123")
{
return new ApiUserToken()
{
AuthScheme = "HMAC",
AccessToken = "94d05acb-54de-4e39-9303-3764cabcaf18",
SecretToken = "88a10072-5fa9-4a8d-b9ac-42966d8da4bc",
Name = "DemoUser",
UserId = "001",
Roles = "Users"
};
}
return null;
}
以下方法用于授权。ApiFrame在授权时调用此方法,将用户的访问令牌作为输入参数传递给该方法。在实际应用程序中,此方法应调用服务或数据访问方法来查询数据库,通过访问令牌获取用户详细信息。该方法使用用户详细信息构建一个ApiUserToken并返回该令牌。
public ApiUserToken GetUserToken(string accessToken)
{
if (accessToken == "94d05acb-54de-4e39-9303-3764cabcaf18")
{
return new ApiUserToken()
{
AuthScheme = "HMAC",
AccessToken = "94d05acb-54de-4e39-9303-3764cabcaf18",
SecretToken = "88a10072-5fa9-4a8d-b9ac-42966d8da4bc",
Name = "DemoUser",
UserId = "001",
Roles = "Users"
};
}
return null;
}
实现IApiException
通过实现此接口可以捕获异常。
public class ApiException : IApiException
{
public void LogMessage(Exception exception)
{
throw new NotImplementedException();
}
}
一旦您完成了接口的实现,需要在项目中添加以下配置,将实现(依赖项)注入到库中。在Global.asax文件中,将以下代码包含在Application_Start()中
// ApiFrameConfiguration
ApiObjectFactory.RegisterType<IApiInception, ApiInception>();
ApiObjectFactory.RegisterType<IApiException, ApiException>();
ApiObjectFactory.RegisterType<IApiSignature, ApiSignature>();
示例Web API方法
如果您对Web API方法进行版本控制感兴趣,ApiFrame提供了使用MVC区域或使用命名空间进行版本控制的选项。让我们尝试使用区域。
创建一个名为“V1”的新MVC区域,并在WebApiConfig.cs文件中进行以下配置。这样,您几乎完成了Web API方法的版本控制设置,其余的您需要处理路由。
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Services.Replace(typeof(IHttpControllerSelector), new ApiControllerSelector(config));
}
}
在V1中创建以下模型
public class AccessModel
{
public string AccessToken { get; set; }
public string SecretToken { get; set; }
}
向项目中添加一个新控制器,并将其命名为“DemoController”。用“ApiException”属性框架DemoController,以允许ApiFrame为您处理异常。
[ApiException]
public class DemoController : ApiController
{
}
将以下方法添加到DemoController。让我们创建以下方法进行演示。
- SignIn - 用于认证演示的POST方法
- 相对路由:/demo/signin
- GetMessage - 用于授权演示的GET方法
- 相对路由:/demo/getmessage
您会注意到,下面的SignIn方法是用ApiAuthentication过滤器属性框起来的。同样,GetMessage是用ApiAuthorization过滤器属性框起来的。这些过滤器属性通过调用IApiInception实现的注入方法来处理认证和授权。
[HttpPost]
[ApiAuthentication]
public AccessModel SignIn()
{
return new AccessModel
{
AccessToken = "94d05acb-54de-4e39-9303-3764cabcaf18",
SecretToken = "88a10072-5fa9-4a8d-b9ac-42966d8da4bc"
};
}
[HttpGet]
[ApiAuthorization(Roles = "Users")]
public string GetMessage()
{
string user = ((ApiIdentity)HttpContext.Current.User.Identity).Name;
return string.Format("Server Message :This is an Authorized Request - LoggedIn User:{0}", user);
}
更新V1AreaRegistration类中的默认路由。
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
"V1_default",
"{area}/{controller}/{action}/{id}",
new { id = UrlParameter.Optional }
);
}
运行应用程序,您将看到以下屏幕。我的示例Web API服务正在URL localhost:6360运行

API客户端应使用相同的URL与服务进行通信。
示例API客户端
为了演示目的,让我们从控制台应用程序消费Web API服务。
- 打开Visual Studio 2012
- 创建控制台应用程序
- 添加对System.Net.Http程序集的引用
- 通过Nuget包管理器安装以下内容
- ApiFrame
- Json.NET
在调用API服务之前,我们需要以下初始设置
// Service Url
string serviceUrl = "https://:6360/";
// Uri version
string apiVersion = "v2";
// Signature Configuration
ApiObjectFactory.RegisterType<IApiSignature, ApiSignature>();
ApiFrame使用HMAC-SHA256算法计算签名。客户端和服务器两端都需要使用相同的算法。为此,我们客户端需要上述签名配置。
服务器将使用令牌识别客户端,因此需要以下配置,并且令牌应与服务器中存储的相同。
// Token Configuration
const string AuthScheme = "HMAC";
const string AccessToken = "d85aa01c-cf92-4f1e-9862-638fa4ae37b4";
const string SecretToken = "06fb3823-b8cc-462b-b855-f655d49eb3e2";
按照以下步骤检查SignIn API服务
- 通过控制台读取用户名和密码
- 创建包含用户名和密码的POST数据
- 使用服务调用所需的参数创建请求令牌
- 通过传递服务URL创建ApiClientGateway实例
- 通过传递请求令牌调用ApiClientGateway的Execute方法
// Authentication - Sing-in demo - START
Console.WriteLine("\n Authentication -> Sign-in demo - START");
Console.Write("\n\n Enter the Username:");
string userName = Console.ReadLine();
Console.Write(" Enter the Password:");
string password = Console.ReadLine();
string postData = string.Format("Username={0}&Password={1}", userName, password);
ApiRequestToken requestToken = new ApiRequestToken()
{
Verb = HttpMethod.Post,
RelativeUrl = string.Format("{0}/demo/signin", apiVersion),
AccessToken = AppAccessToken,
SecretToken = AppSecretToken,
AuthScheme = AuthScheme,
Content = postData
};
ApiClientGateway apiClientGateway = new ApiClientGateway(serviceUrl);
AccessModel signInResult = null;
try
{
signInResult = apiClientGateway.Execute<AccessModel>(requestToken);
if (signInResult != null)
{
Console.WriteLine("\n Response from server");
Console.WriteLine("\n AccessToken:" + signInResult.AccessToken);
Console.WriteLine(" SecretToken:" + signInResult.SecretToken);
Console.WriteLine("\n Successfully Authenticated! This is ApiAuthentication Test");
}
}
catch (ApiRequestException ex)
{
Console.WriteLine(ex.ErrorResponseMessage.
Content.ReadAsStringAsync().Result);
}
// Sing-in demo - END

在调用登录服务时,服务器在成功认证后返回一个令牌(访问令牌和秘密令牌)。此令牌被保留并用于后续服务调用。以下是调用授权API服务方法返回私有消息的示例。让我们使用接收到的令牌进行下一次服务调用以获取私有消息
// Authorization -> GetMessage demo - Start
Console.WriteLine("\n Authorization demo -> GetMessage - START");
Console.Read();
if (signInResult != null)
{
requestToken = new ApiRequestToken()
{
Verb = HttpMethod.Get,
RelativeUrl = string.Format("{0}/demo/GetMessage", apiVersion),
AccessToken = signInResult.AccessToken,
SecretToken = signInResult.SecretToken,
AuthScheme = AuthScheme
};
string messageResult = string.Empty;
try
{
messageResult = apiClientGateway.Execute(requestToken);
if (!string.IsNullOrEmpty(messageResult))
{
Console.WriteLine("\n This is ApiAuthorization test");
Console.WriteLine("Server Response :" + messageResult);
}
}
catch (ApiRequestException ex)
{
Console.WriteLine(ex.ErrorResponseMessage.
Content.ReadAsStringAsync().Result);
}
}
Console.Read();
// Authorization -> GetMessage demo - End

发生异常时,服务返回ApiRequestException类型的异常。以下显示的是使用错误凭据登录服务调用的屏幕截图。
catch (ApiRequestException ex)
{
Console.WriteLine(ex.ErrorResponseMessage.
Content.ReadAsStringAsync().Result);
}

API版本控制演示
在Web API项目中,让我们创建一个新版本的“DemoController”,并添加新版本的SignIn和GetMessage服务。
- 创建一个名为“V2”的新MVC区域
- 添加一个新的“DemoController”和“AccessModel”
- 从V1版本复制SignIn和GetMessage服务
- 更新GetMessage服务以包含新版本的消息
- 运行应用程序并保持服务启动并运行
在API客户端中,更新apiVersion并运行应用程序。授权服务“GetMessage”现在将返回新版本更新的消息。
