首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >ASP.NET核心Web身份验证允许未经授权的访问

ASP.NET核心Web身份验证允许未经授权的访问
EN

Stack Overflow用户
提问于 2019-07-11 04:28:04
回答 2查看 10.7K关注 0票数 1

我正在为我的ASP.NET核心API创建一个身份验证方案。

它调用我的处理程序并命中断点,但是API调用仍然返回结果,即使授权失败。

代码语言:javascript
代码运行次数:0
运行
复制
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    if (!Request.Headers.ContainsKey(AuthorizationHeaderName))
    {
        //Authorization header not in request
        return AuthenticateResult.Fail("Missing Authorization header");
    }

在我天真的理解中,如果身份验证失败,它不应该返回数据。

我遗漏了什么?

详细信息

我在Startup.ConfigureServices中注册了这样的方案

代码语言:javascript
代码运行次数:0
运行
复制
services.AddAuthentication(options => {
    // This (options.Default..Scheme) causes the default authentication scheme to be set.
    // Without this, the Authorization header is not checked and
    // you'll get no results. 
   options.DefaultAuthenticateScheme = BasicAuthenticationDefaults.AuthenticationScheme;
}).AddScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>("Basic", null);

Startup.Config调用

代码语言:javascript
代码运行次数:0
运行
复制
 app.UseAuthentication();
 app.UseHttpsRedirection();
 app.UseMvc();

其余代码如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;

namespace WebAPI.Authentication
{
    public interface IBasicAuthenticationService
    {
        Task<AuthenticateResult> HandleAuthenticateAsync();
    }

    public static class BasicAuthenticationDefaults
    {
        public const string AuthenticationScheme = "Basic";
    }

    public class BasicAuthenticationOptions : AuthenticationSchemeOptions
    { }

    public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions>
    {
        private const string AuthorizationHeaderName = "Authorization";
        private const string BasicSchemeName = "Basic";

        public BasicAuthenticationHandler(
            IOptionsMonitor<BasicAuthenticationOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock)
            : base(options, logger, encoder, clock)
        {
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey(AuthorizationHeaderName))
            {  // Rejected here. Should fail.
                //Authorization header not in request
                return AuthenticateResult.Fail("Missing Authorization header");
            }

            if ....  // never gets this far
            }

            return AuthenticateResult.Success(ticket);
        }
    }
}

这是控制器,它不正确地返回结果。

代码语言:javascript
代码运行次数:0
运行
复制
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace TMAWebAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }
    } 
}

所有这些代码行都会在调试器中命中,因此该部分似乎工作正常。

但是API调用仍然返回结果,即使它失败了身份验证。

更新:

向Controller添加AuthenticationScheme属性会使其失败。

如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
[Route("api/[controller]")]
[ApiController]
[Authorize(AuthenticationSchemes = "Basic")]
public class ValuesController : ControllerBase

这不是好事。默认情况下,它应该失败,而不是必须将其添加到每个控制器中。

更新2:

向services.AddMvc添加一个过滤器看起来很有希望,但也不起作用。文档声明您不必实现授权筛选器,因为它们包括在内。我找不到。

我继承了AuthorizeAttribute,使用了AddMvc所要求的Matti和IFilterMetadata的想法。它编译但仍然允许未经授权的访问。

代码语言:javascript
代码运行次数:0
运行
复制
public class BasicAuthorizeAttribute : AuthorizeAttribute, IFilterMetadata { }       

services.AddMvc(options => {
    options.Filters.Add(typeof(BasicAuthorizeAttribute));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

更新3:

试过

代码语言:javascript
代码运行次数:0
运行
复制
policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser()

就像马蒂建议的那样,但那又回来了

代码语言:javascript
代码运行次数:0
运行
复制
InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.

我对重定向到API不存在的登录页面没有任何兴趣,所以我尝试了。

代码语言:javascript
代码运行次数:0
运行
复制
policy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes(new[] {BasicAuthenticationDefaults.AuthenticationScheme })

它编译但抛出异常。

代码语言:javascript
代码运行次数:0
运行
复制
InvalidOperationException Message=AuthorizationPolicy must have at least one requirement.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-13 04:23:27

您需要将[Authorize]属性添加到控制器中,以使授权能够实际对其结果执行任何操作。您可以在全球范围内添加如下内容:

代码语言:javascript
代码运行次数:0
运行
复制
services.AddMvc(config =>
{
    var policy = new AuthorizationPolicyBuilder()
                 .RequireAuthenticatedUser()
                 .Build();
    config.Filters.Add(new AuthorizeFilter(policy));
});
票数 2
EN

Stack Overflow用户

发布于 2019-07-17 18:50:20

最后的分辨率使用AddMVC。解决办法是,除了增加一个方案外,该计划还需要一个要求。

这挺管用的。如果我没有发送任何auth标头,它将返回一个空页。如果我发送过期的标头,它会发送500。应该是401。但它不返回任何值,这才是我真正关心的。

代码语言:javascript
代码运行次数:0
运行
复制
public class TokenAuthorizationRequirement: IAuthorizationRequirement {}

services.AddMvc(config => {
   var policy = new AuthorizationPolicyBuilder()
      .AddAuthenticationSchemes(new[] {BasicAuthenticationDefaults.AuthenticationScheme })
      .AddRequirements(new BasicAuthorizationRequirement())
      .Build();
   config.Filters.Add(new AuthorizeFilter(policy));
});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56981640

复制
相关文章

相似问题

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