ASP.NET Core识别Auth + Angular:登录不起作用

时间:2018-07-16 12:31:38

标签: c# angular authentication asp.net-core asp.net-core-identity

我目前正在开发具有ASP.NET Core(2.1)API服务器/后端和Angular单页应用程序前端的应用程序。

对于用户身份验证,我使用的是ASP.NET Core Identity,以及AccountController中提供的几种默认方法,用于登录,注销,注册,忘记密码等。我的Angular应用程序通过以下方式访问此API:执行这些操作。

Angular客户端文件直接从wwwroot中托管在ASP.NET Core应用程序中。我在localhost:5000下使用IIS Express托管(我也尝试过IIS,但无济于事)。

使用以下内容在ASP.NET Core的Startup类中配置身份验证:

services.AddIdentity<ApplicationUser, IdentityRole>(config =>
    {
        config.SignIn.RequireConfirmedEmail = false;
        config.Password.RequiredLength = 8;
    })
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

// Prevent API from redirecting to login or Access Denied screens (Angular handles these).
services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = 401;
        return Task.CompletedTask;
    };
    options.Events.OnRedirectToAccessDenied = context =>
    {
        context.Response.StatusCode = 403;
        return Task.CompletedTask;
    };
});

注册和忘记密码都可以顺利进行。调用该API并采取适当的措施。

登录出现起作用:该方法在Angular中调用:

@Injectable()
export class AuthService extends BaseService {
  constructor(private httpClient: HttpClient) {
    super(httpClient, `${config.SERVER_API_URL}/account`);
  }

  // Snip

  login(login: Login): Observable<boolean> {
    return this.httpClient.post<boolean>(`${this.actionUrl}/Login`, login)
      .catch(this.handleError);
  }

  // Snip
}

ASP.NET Core API获取调用,登录用户并返回成功,以向Angular指示登录有效,并且他们应继续重定向用户:

namespace ApartmentBonds.Web.Api.Account
{
    [Route("api/[controller]/[action]")]
    public class AccountController : APIControllerBase
    {
        // Snip

        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] LoginViewModel model, string returnUrl = null)
        {
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, false);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    return Ok(true);
                }
            }

            return Ok(false);
        }

        // Snip
    }
}

会话cookie创建成功,并且可以在浏览器中看到它(在此屏幕截图中使用Firefox Quantum,但也已在IE,Firefox隐身模式下尝试过):

Cookie

为了进行测试,我有另一个API方法,该方法仅返回调用用户是否已登录:

// Angular
isLoggedIn(): Observable<boolean> {
  return this.httpClient.get<boolean>(`${this.actionUrl}/IsLoggedIn`)
    .catch(this.handleError);
}

// ASP.NET Core API
[HttpGet]
[AllowAnonymous]
public IActionResult IsLoggedIn()
{
    return Ok(_signInManager.IsSignedIn(User));
}

我在浏览器中进行此调用,,它返回false 。 (依赖于登录用户的网站的所有其他方面也显示用户尚未登录-此方法只是验证此问题的一种快速而肮脏的方法。)请注意,客户端正在正确发送身份cookie。连同请求:

IsLoggedIn Request

由于这里唯一有问题的网站是localhost:5000,所以我不确定为什么它不起作用。

我尝试过的事情

  • services.ConfigureApplicationCookie之内
    • 明确地将options.Events.Cookie.Domain设置为localhost:5000
    • options.Events.Cookie.Path设置为/api
  • 清除所有cookie并尝试使用隐身/其他浏览器(以排除可能影响请求的其他localhost站点cookie)
  • 发布核心应用程序后,通过IIS(localhost:8888)托管网站

有人有什么想法吗?

3 个答案:

答案 0 :(得分:2)

为了使身份验证处理程序能够在请求上运行,您需要在中间件管道中使用app.UseAuthentication();(在需要像MVC这样的中间件之前)。

答案 1 :(得分:0)

这是一个远景,但是令牌可能需要:在实际令牌前面带有空格的“承载者”。

答案 2 :(得分:0)

我认为在使用 AllowAnonymousAttribute 时,不应使用控制器的 User 属性。

尝试向某些授权端点发出请求。如果您未登录,则将获得状态码401(未授权)。