上下文
我们正在使用Asp.Net Core(Web Api)迁移Web应用程序以使用Angular2 单页应用程序(SPA)前端。该应用程序最初使用"个人用户帐户"进行。我们一直在将cshtml视图转换为Angular2组件,生成Json的控制器方法,甚至将JWT用于身份验证。
我一直在使用这个Configuring Google authentication微软文档。
问题
以下两种控制器方法说明了这个问题。 LinkLogin
方法返回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
,我会收到此回复:
对预检请求的响应没有通过访问控制检查:否&#39;访问控制 - 允许 - 来源&#39;标头出现在请求的资源上。起源&#39; http://localhost:53462&#39;因此不允许访问。响应的HTTP状态代码为405。
答案 0 :(得分:0)
所以我最终想出了一个通过修改Angular2和WebApi之间的流程来避免“ChallengeResult”的解决方案。
angular2-social-login
npm包添加到角度应用中(跟随所有easy instructions for setup)。将两种控制器方法合并为一种。 ExternalLoginViewModel
参数是一个带有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客户端以使用社交媒体包获取Web 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
}