我們會先對API項目進行必要的修改,修改完成後再切換到Web項目來更新客戶端。
步驟1:我們需要壹個數據庫。
在做任何事情之前,我們需要創建壹個數據庫。在此示例中,將使用SQL Server Express。如果沒有安裝,可以從這裏下載SQL Server Express。安裝完成後,創建壹個名為CallingWebApiFromMvc的數據庫。這是第壹步。
Api項目還需要壹個數據庫連接字符串,否則我們無法前進。將以下代碼插入Api項目的Web.config文件中:
& ltconnectionStrings & gt
& ltadd name = " ApiFromMvcConnection " connectionString = " Data Source =(local);初始目錄= CallingWebApiFromMvcintegrated Security = True " providerName = " System。Data.SqlClient" />& lt/connection strings & gt;
Identity framework會自動創建我們管理用戶所需的成員資格表,所以現在不必擔心提前創建它們。
第2步:添加相關的Nuget包。
接下來,我們為OWIN和Windows身份驗證添加Nuget包。打開包管理控制臺,將Api項目切換到默認項目,並輸入以下命令:
安裝包微軟。AspNet.WebApi.Owin
安裝包微軟。Owin.Host.SystemWeb
安裝包微軟。AspNet . identity . entity framework
安裝包微軟。AspNet.Identity.Owin
使用這些包,我們可以在應用程序中啟動壹個OWIN服務器,然後通過EntityFramework將我們的用戶保存到SQL Server。
步驟3:添加管理用戶的身份類。
我們使用基於Windows認證機制的實體框架來管理數據庫相關業務。首先,我們需要添加壹些用於處理的類。向Api項目添加壹個身份目錄,作為我們要添加的類的名稱空間。然後添加以下類:
公共類應用程序用戶:標識用戶
{
}
公共類ApplicationDbContext:IdentityDbContext & lt;應用程序用戶& gt
{ public ApplicationDbContext():base(" apifromvcconnection "){ }
公共靜態應用程序DbContext Create()
{ return new ApplicationDbContext();
}
}
請註意,我們傳遞給基類構造函數的參數ApiFromMvcConnection應該與Web.config中連接字符串中的名稱相匹配。
公共類application user manager:user manager & lt;應用程序用戶& gt
{公共應用程序用戶管理器(IUserStore & lt應用程序用戶& gt商店) :基地(商店)
{
}公共靜態application user manager Create(IdentityFactoryOptions & lt;ApplicationUserManager & gt選項,低上下文上下文)
{ var manager = new application user manager(new user store & lt;應用程序用戶& gt(上下文。獲取& ltApplicationDbContext & gt()));
//為用戶名配置驗證邏輯
經理。user validator = new user validator & lt;應用程序用戶& gt(經理)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
//配置密碼的驗證邏輯
經理。PasswordValidator =新PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
require大寫= true,
};var data protection provider = options。DataProtectionProvider
if (dataProtectionProvider!=空)
{
經理。UserTokenProvider = new data protectortokenprovider & lt;應用程序用戶& gt(dataProtectionProvider。Create("ASP。網名”));
}退貨經理;
}
}
步驟4:添加OWIN啟動類
為了讓我們的應用程序作為OWIN服務器運行,我們需要在應用程序啟動時初始化它。我們可以通過壹個啟動類來做到這壹點。我們將裝飾這種
OwinStartup屬性,因此它在應用程序啟動時被觸發。這也意味著我們可以去掉Global.asax,把它們移走。
Application_Start代碼被轉換成我們新的啟動類。
使用微軟。Owin
[assembly:OwinStartup(type of(Levelnis。learning . callingwebapifrommvc . API . startup))]
命名空間級別。learning . calling webapifrommvc . API
{
使用系統;
使用系統。Web . Http
利用身份;
使用微軟。Owin . Security.OAuth
使用Owin
使用提供商;
公共類啟動
{公共void配置(IAppBuilder應用程序)
{
全局配置。配置(WebApiConfig。註冊);
app。CreatePerOwinContext(ApplicationDbContext。創建);
app。CreatePerOwinContext & ltApplicationUserManager & gt(ApplicationUserManager。創建);var oauth options = new OAuthAuthorizationServerOptions
{
TokenEndpointPath =新路徑字符串("/api/token "),
provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan。FromDays(1),
AllowInsecureHttp = true
};
//允許應用程序使用不記名令牌對用戶進行身份驗證
app。UseOAuthBearerTokens(oauth options);
}
}
}
當應用程序啟動時,我們正在構建自己的服務器。在這裏,我們配置令牌端點並設置我們自己的定制提供者,我們使用我們的用戶進行身份驗證。在我們的示例中,我們使用了ApplicationOAuthProvider類。讓我們看看現在:
步驟5:添加OAuth的提供者
公共類ApplicationOAuthProvider:OAuthAuthorizationServerProvider
{公共覆蓋任務ValidateClientAuthentication(OAuthValidateClientAuthenticationContext)
{
語境。已驗證();
返回任務。FromResult & ltobject & gt(空);
}
公共重寫異步任務GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext)
{
var userManager =上下文。OwinContext . GetUserManager & ltApplicationUserManager & gt();
var user = await userManager。FindAsync(上下文用戶名,上下文。密碼);
if (user == null)
{
語境。SetError("invalid_grant ","用戶名或密碼不正確。");返回;
}
var oAuthIdentity = await用戶。GenerateUserIdentityAsync(user manager,OAuthDefaults。AuthenticationType);var cookiesIdentity = await用戶。GenerateUserIdentityAsync(user manager,CookieAuthenticationDefaults。AuthenticationType);var properties = create properties(user。用戶名);var ticket = new AuthenticationTicket(oauth identity,properties);
語境。已驗證(票);
語境。request . context . authentic ation . sign in(cookies identity);
}
私有靜態身份驗證屬性創建屬性(字符串用戶名)
{
var data =新字典& ltstring,string & gt
{
{
“用戶名”,用戶名
}
};
返回新的AuthenticationProperties(數據);
}
}
我們對這裏的兩種方法感興趣。首先,ValidateClientAuthentication只是驗證客戶端。我們有壹個客戶,所以我們返回。
工作。這是壹個異步方法簽名,但沒有發生異步調用。正因為如此,我們可以離開異步修改,但我們必須自己返回到壹個任務。我們添加了壹個名為。
GenerateUserIdentityAsync的ApplicationUser,看起來像這樣的方法:
公共類應用程序用戶:標識用戶
{公共異步任務& ltClaimsIdentity & gtGenerateUserIdentityAsync(user manager & lt;應用程序用戶& gt經理,字符串身份驗證類型)
{
var userIdentity = await manager。CreateIdentityAsync(this,authenticationType);
返回用戶標識;
}
}
步驟6:註冊壹個新的用戶API端
因此,我們已經有了所有的身份類管理用戶。讓我們看壹下RegisterController並將新用戶保存到我們的數據庫中。它接受壹個簡單的RegisterApi模式:
公共類RegisterApiModel
{
[必需]
[EmailAddress]公共字符串Email { get設置;}
[必需]
[StringLength(100,ErrorMessage = "該{0}的長度必須至少為{2}個字符。",最小長度= 6)]
公共字符串密碼{
get設置;
}
[必需]
[顯示(Name = "確認密碼")]
[Compare("Password ",ErrorMessage = "密碼和確認密碼不匹配。")]
公共字符串ConfirmPassword { get設置;}
}
如果註冊成功,控制器本身僅返回200 OK響應。如果驗證失敗,則返回401錯誤請求的響應。
公共類register controller:API controller
{私有應用程序用戶管理器用戶管理器
{獲取
{退貨請求。GetOwinContext()。GetUserManager & ltApplicationUserManager & gt();
}
} public IHttpActionResult Post(RegisterApiModel模型)
{如果(!模型狀態。IsValid)
{ return bad request(model state);
} var user =新應用程序用戶
{
郵件=模型。電子郵件,
用戶名=型號。電子郵件,
EmailConfirmed = true
};
var result = UserManager。創建(用戶,模型。密碼);
返回結果。成功了?Ok() : GetErrorResult(結果);
}
private IHttpActionResult get error result(identity result結果)
{
if(結果== null)
{
返回internal server error();
}
如果(結果。錯誤!=空)
{
foreach(結果中的變量錯誤。錯誤)
{
模型狀態。AddModelError(",錯誤);
}
}
if (ModelState。IsValid)
{
//沒有可發送的ModelState錯誤,因此只返回壹個空的BadRequest。
返回bad request();
}
返回bad request(model state);
}
}