首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ASP.NET 6 Restful Api无法使用cookie进行身份验证

ASP.NET 6 Restful Api无法使用cookie进行身份验证
EN

Stack Overflow用户
提问于 2022-06-16 14:03:08
回答 2查看 708关注 0票数 0

我正在开发一个ASP.NET 6 Restful作为拼贴作业。我想在我的API中引入AAA。我有很多允许的选项,我选择了核心身份+cookie。我尽可能多地学习教程,但没有结果。

我没有任何具体的客户端(我的任务不包括一个),我使用邮递员和Telerik发送请求。

我的主要问题是:在我使用我的端点登录之后,我仍然不能对用户进行身份验证并访问非匿名端点。如果我尝试使用它们,我会得到一个重定向:

代码语言:javascript
运行
复制
[15:35:24 INF] Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
[15:35:24 INF] AuthenticationScheme: Identity.Application was challenged.
[15:35:24 INF] HTTP GET /api/User/getDemoAuthorized responded 302 in 48.2047 ms
[15:35:24 INF] Request finished HTTP/2 GET https://localhost:7166/api/User/getDemoAuthorized - - - 302 0 - 98.8841ms
[15:35:24 INF] Request starting HTTP/2 GET https://localhost:7166/Identity/Account/Login?ReturnUrl=%2Fapi%2FUser%2FgetDemoAuthorized - -
[15:35:24 DBG] No candidates found for the request path '/Identity/Account/Login'
[15:35:24 DBG] Request did not match any endpoints
[15:35:24 DBG] The request path  does not match the path filter
[15:35:24 DBG] The request path /Identity/Account/Login does not match a supported file type
[15:35:24 DBG] AuthenticationScheme: Identity.Application was not authenticated.
[15:35:24 DBG] List of registered output formatters, in the following order: ["Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.StringOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter", "Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter"]
[15:35:24 DBG] No information found on request to perform content negotiation.
[15:35:24 DBG] Attempting to select the first output formatter in the output formatters list which supports a content type from the explicitly specified content types '["application/problem+json", "application/problem+xml", "application/problem+json", "application/problem+xml"]'.
[15:35:24 DBG] Selected output formatter 'Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter' and content type 'application/problem+json' to write the response.
[15:35:24 INF] Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ProblemDetails'.
[15:35:24 INF] HTTP GET /Identity/Account/Login responded 404 in 36.7039 ms

注意:我不能使用Razor网页,只是一个简单的restful。

当使用匿名端点时,我可以看到我的用户没有经过身份验证:用户未验证图片

当我尝试登录时的日志:

代码语言:javascript
运行
复制
[15:53:37 DBG] Context 'AppDbContext' started tracking 'IdentityUser' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
[15:53:37 DBG] A data reader was disposed.
[15:53:37 DBG] Closing connection to database 'caloryDb' on server '(localdb)\MSSQLLocalDB'.
[15:53:37 DBG] Closed connection to database 'caloryDb' on server '(localdb)\MSSQLLocalDB'.
[15:53:40 INF] AuthenticationScheme: caloryCookieAuth signed in.
[15:53:40 INF] Executing StatusCodeResult, setting HTTP status code 204
[15:53:40 INF] Executed action CaloryWebApi.Api.Controllers.UserController.LoginAsync (CaloryWebApi.Api) in 7301.0998ms
[15:53:40 INF] Executed endpoint 'CaloryWebApi.Api.Controllers.UserController.LoginAsync (CaloryWebApi.Api)'
[15:53:40 INF] HTTP POST /api/User/login responded 204 in 7407.4312 ms

用户控制器:

代码语言:javascript
运行
复制
[Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class UserController : ControllerBase
    {

        private readonly IUserService _userService;
        private readonly SignInManager<IdentityUser> _signInManager;

        public UserController(IUserService userService, SignInManager<IdentityUser> signInManager)
        {
            _userService = userService;
            _signInManager = signInManager;
        }

        [HttpGet("getDemoAnonymous")]
        [AllowAnonymous]
        public ActionResult GetDemo()
        {
            List<string> demo = new List<string>() { "Authorization demo - anonymous" , "test" };
            return Ok(demo);
        }

        [HttpGet("getDemoAuthorized")]
        public ActionResult GetDemoAuthentitaced()
        {
            List<string> demo = new List<string>() { "Authorization demo - auth ok" , "test" };
            return Ok(demo);
        }

        [AllowAnonymous]
        [HttpPost("login")]
        public async Task<ActionResult> LoginAsync([FromBody] LoginModelType loginModelType)
        {
            var user = await _userService.GetUser(loginModelType.Email);
            if (user != null) // We found a user mathing this email address
            {
                var signInResult = await _signInManager.CheckPasswordSignInAsync(user,loginModelType.Password,false);

                if (signInResult.Succeeded)
                {

                    var identity = new ClaimsIdentity(claims : new Claim[]
                         {
                        new Claim(ClaimTypes.Name, loginModelType.Email)
                         },
                         authenticationType : "caloryCookieAuth")
                    {
                    };
                    var claimsPrincipal = new ClaimsPrincipal(identity);

                    await HttpContext.SignInAsync("caloryCookieAuth", claimsPrincipal);

                    return NoContent();
                }
                else
                {
                    return BadRequest("Failed to authenticate user. Try again!");
                }
            }
            return BadRequest("Failed to authenticate user. Try again!");
        }

        [HttpPost("logout")]
        public async Task<ActionResult> LogoutAsync()
        {
            await HttpContext.SignOutAsync();
    return NoContent();
        }

        [HttpPost("register")]
        [AllowAnonymous]
        public async Task<ActionResult> RegisterAsync([FromBody] LoginModelType loginModelType)
        {
            var result = await _userService.RegisterUser(loginModelType.Email, loginModelType.Password);

            if(result.Succeeded)
            {
                return NoContent();
            }
            else
            {
                List<string> errorList = new();
                errorList.Add("Failed to register...");
                foreach(var error in result.Errors)
                {
                    errorList.Add($"Error code: {error.Code} - {error.Description}");
                }

                return BadRequest(new { Result = errorList });
            }
        }
    }

我的Program.cs:

代码语言:javascript
运行
复制
 ... 


var builder = WebApplication.CreateBuilder(args);

 ...

builder.Services.AddDbContext<AppDbContext>(o =>
    o.UseSqlServer(builder.Configuration["ConnectionStrings:DefaultConnection"]));

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "caloryCookieAuth";
})
    .AddCookie("caloryCookieAuth", options =>
    {
        options.Cookie.Name = "caloryCookieAuth";
        options.Cookie.SameSite = SameSiteMode.None; //TODO is this important?
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromDays(1);
        options.SlidingExpiration = true;

        options.LoginPath = "/api/User/login";
        options.LogoutPath = "/api/User/logout";

    });


builder.Services.AddDefaultIdentity<IdentityUser>(options => {
     // Configure user identity options here
    options.User.RequireUniqueEmail = true;
})
    .AddEntityFrameworkStores<AppDbContext>();

...


var app = builder.Build();

```...```

app.UseHttpsRedirection();

app.UseCookiePolicy();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

代码语言:javascript
运行
复制

编辑:我更新了问题,包括整个用户控制器

EN

回答 2

Stack Overflow用户

发布于 2022-06-17 05:18:40

如果您想在Cookie.SameSite = SameSiteMode.None中使用AddCookie(),也需要设置Secure = true,如果不设置SecureCookie.SameSite = SameSiteMode.None将无法工作,并且项目将不会发送自定义cookie,请参阅以下代码:

代码语言:javascript
运行
复制
.AddCookie("caloryCookieAuth", options =>
    {
        options.Cookie.Name = "caloryCookieAuth";

        //add this to configure Secure

        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.SameSite = SameSiteMode.None; //TODO is this important?
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromDays(1);
        options.SlidingExpiration = true;

        options.LoginPath = "/api/User/login";
        options.LogoutPath = "/api/User/logout";

    });
票数 0
EN

Stack Overflow用户

发布于 2022-06-18 15:53:24

在检查了所有的建议后,我尝试了最后一件事。我用[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]标记为控制器指定了授权方案。现在看来起作用了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72647199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档