WebApi ChallengeResult 如何合并到 Angular2 SPA 中?
How can WebApi ChallengeResult be incorporated into an Angular2 SPA?
上下文
我们正在使用 Asp.Net 核心(Web Api)迁移 Web 应用程序以使用 Angular2
单页应用程序 (SPA) 前端。该申请最初是用 "Individual User Accounts" 提出的。我们一直在将 cshtml 视图转换为 Angular2 组件,生成控制器方法 Json,甚至结合 JWT 进行身份验证。
我一直在使用这个 Configuring Google authentication 微软文档。
问题
以下两个控制器方法说明了该问题。 LinkLogin
方法 returns 一个 ChallengeResult
动作。显然这不能转换为JSON。我假设 这个结果应该会导致浏览器重定向到外部登录提供程序,然后自动重定向到 LinkLoginCallback
.
[HttpPost]
public async Task<IActionResult> LinkLogin([FromBody] string provider)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(externalCookieScheme);
// Request a redirect to the external login provider to link a login for the current user
string redirectUrl = Url.Action(nameof(LinkLoginCallback), "Manage");
var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, userManager.GetUserId(User));
return Challenge(properties, provider);
}
[HttpPost]
[Produces("application/json")]
public async Task<ActionResult> LinkLoginCallback()
{
User user = await userManager.GetUserAsync(User);
if (user == null)
return Json(false);
ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync(await userManager.GetUserIdAsync(user));
if (info == null)
return Json(false);
IdentityResult result = await userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(externalCookieScheme);
return Json(true);
}
return Json(false);
}
如果我确实尝试从 Angular 调用 LinkLogin
,我会收到以下响应:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:53462' is therefore not allowed access. The response had HTTP status code 405.
所以我最终想出了一个解决方案,通过修改 Angular2 和 WebApi 之间的流程来避免 "ChallengeResult"。
- 将
angular2-social-login
npm 包添加到 angular 应用程序(在他们的所有 easy instructions for setup 之后)。
将两种控制器方法合并为一个。 ExternalLoginViewModel
参数是一个简单的 class,具有 Email、ProviderKey 和 LoginProvider 属性(在第 3 步的 Angular 中填充):
[HttpPost]
[Produces("application/json")]
public async Task<ActionResult> LinkLogin([FromBody] ExternalLoginViewModel info)
{
if (ModelState.IsValid)
{
User user = await userManager.GetUserAsync(User);
if (user != null)
{
IdentityResult result = await userManager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.LoginProvider));
if (result.Succeeded)
return Json(true);
}
}
return Json(false);
}
更改了 Angular2 客户端以使用社交媒体包获取网络 api 所需的凭据。这是我的 LinkProvider
方法演示连接:(this.service.LinkLogin
调用 LinkLogin
控制器方法)
public async LinkProvider(providerName: string): Promise<void>
{
const result: any = await this.auth.login(providerName).toPromise();
const success: boolean = await this.service.LinkLogin({
email: result.email,
loginProvider: result.provider,
providerKey: result.uid
});
// Handle link response here
}
上下文
我们正在使用 Asp.Net 核心(Web Api)迁移 Web 应用程序以使用 Angular2 单页应用程序 (SPA) 前端。该申请最初是用 "Individual User Accounts" 提出的。我们一直在将 cshtml 视图转换为 Angular2 组件,生成控制器方法 Json,甚至结合 JWT 进行身份验证。
我一直在使用这个 Configuring Google authentication 微软文档。
问题
以下两个控制器方法说明了该问题。 LinkLogin
方法 returns 一个 ChallengeResult
动作。显然这不能转换为JSON。我假设 这个结果应该会导致浏览器重定向到外部登录提供程序,然后自动重定向到 LinkLoginCallback
.
[HttpPost]
public async Task<IActionResult> LinkLogin([FromBody] string provider)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(externalCookieScheme);
// Request a redirect to the external login provider to link a login for the current user
string redirectUrl = Url.Action(nameof(LinkLoginCallback), "Manage");
var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, userManager.GetUserId(User));
return Challenge(properties, provider);
}
[HttpPost]
[Produces("application/json")]
public async Task<ActionResult> LinkLoginCallback()
{
User user = await userManager.GetUserAsync(User);
if (user == null)
return Json(false);
ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync(await userManager.GetUserIdAsync(user));
if (info == null)
return Json(false);
IdentityResult result = await userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(externalCookieScheme);
return Json(true);
}
return Json(false);
}
如果我确实尝试从 Angular 调用 LinkLogin
,我会收到以下响应:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:53462' is therefore not allowed access. The response had HTTP status code 405.
所以我最终想出了一个解决方案,通过修改 Angular2 和 WebApi 之间的流程来避免 "ChallengeResult"。
- 将
angular2-social-login
npm 包添加到 angular 应用程序(在他们的所有 easy instructions for setup 之后)。 将两种控制器方法合并为一个。
ExternalLoginViewModel
参数是一个简单的 class,具有 Email、ProviderKey 和 LoginProvider 属性(在第 3 步的 Angular 中填充):[HttpPost] [Produces("application/json")] public async Task<ActionResult> LinkLogin([FromBody] ExternalLoginViewModel info) { if (ModelState.IsValid) { User user = await userManager.GetUserAsync(User); if (user != null) { IdentityResult result = await userManager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.LoginProvider)); if (result.Succeeded) return Json(true); } } return Json(false); }
更改了 Angular2 客户端以使用社交媒体包获取网络 api 所需的凭据。这是我的
LinkProvider
方法演示连接:(this.service.LinkLogin
调用LinkLogin
控制器方法)public async LinkProvider(providerName: string): Promise<void> { const result: any = await this.auth.login(providerName).toPromise(); const success: boolean = await this.service.LinkLogin({ email: result.email, loginProvider: result.provider, providerKey: result.uid }); // Handle link response here }