【问题标题】:Authorization issue in ASP.NET Core hosted Blazor templateASP.NET Core 托管的 Blazor 模板中的授权问题
【发布时间】:2019-12-20 14:34:39
【问题描述】:

我在 api 的控制器函数上使用 [Authorize] 属性,它总是显示数据,这些属性不起作用,当我调试身份用户时,我发现它没有经过身份验证,但它总是发送 json 数据,而它不应该发送经过身份验证的响应,任何帮助知道为什么授权属性不起作用?

using System;
using System.IO.Compression;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using MedicalDivision.Server.Security;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace test.Server
{
    public class Startup
    {
        private X509Certificate2 Cert { get; }
        private IConfiguration Configuration { get; }
        private IWebHostEnvironment Env { get; }
        private ITokenProvider TokenProvider { get; }
        private PasswordHelper PasswordHelper { get; }
        private IHttpContextAccessor httpContextAccessor { get; }
        private IServiceProvider ServiceProvider { get; }

        public readonly string _myAllowSpecificOrigins = "_myAllowSpecificOrigins";

        public Startup(IConfiguration configuration,IWebHostEnvironment env,IServiceProvider serviceProvider)
        {
            ServiceProvider = serviceProvider;
            Configuration = configuration;
            Env = env;
            Cert = new X509Certificate2(Convert.FromBase64String(Configuration["Auth:Cert:Data"]),  Configuration["Auth:Cert:Password"], X509KeyStorageFlags.MachineKeySet);
            TokenProvider =new JwtTokenProvider(Cert, Configuration,env);
            PasswordHelper = new PasswordHelper();
            httpContextAccessor = ServiceProvider.GetService<IHttpContextAccessor>();
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(serviceProvider => new AuthManager(Configuration,TokenProvider));


            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o =>
            {
                o.TokenValidationParameters = TokenProvider.GetValidationParameters();
                o.SecurityTokenValidators.Clear();
                o.SecurityTokenValidators.Add(new CustomTokenValidator(ServiceProvider));
            });
            services.AddAuthorization();
            services.AddResponseCompression(opts =>
            {
                opts.EnableForHttps = true;
                opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "application/octet-stream", "image/png", "font/otf", "image/gif", "image/x-icon", "image/jpeg", "application/pdf", "image/svg+xml", "font/ttf", "font/woff", "font/woff2", "application/xml", "text/csv" });
            });
            services.Configure<GzipCompressionProviderOptions>(o =>
            {
                o.Level = CompressionLevel.Optimal;
            });
            services.AddCors(options =>
            {
                options.AddPolicy(_myAllowSpecificOrigins,
                    builder =>
                    {
                        builder
                            .AllowAnyOrigin() 
                            .AllowAnyMethod()
                            .AllowAnyHeader();
                            //.AllowCredentials();
                    });
            });
            services.AddMvc().AddNewtonsoftJson();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
             app.UseAuthentication();
            app.UseAuthorization(); 
            app.UseResponseCompression();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBlazorDebugging();
            }

            app.UseCors(_myAllowSpecificOrigins);
            app.UseStaticFiles();
            app.UseClientSideBlazorFiles<Client.Startup>();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
                endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
            });
        }
    }
}

和自定义验证类:

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

namespace test.Server.Security
{
    public class CustomTokenValidator : ISecurityTokenValidator
    {
        private readonly JwtSecurityTokenHandler _tokenHandler;
        //private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly HttpContextAccessor _httpContextAccessor = new HttpContextAccessor();

        public CustomTokenValidator(IServiceProvider serviceProvider)
        {
            _tokenHandler = new JwtSecurityTokenHandler();
           // _httpContextAccessor = httpContextAccessor;
           // _httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();

        }

        public bool CanValidateToken => true;

        public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;

        public bool CanReadToken(string securityToken)
        {
            return _tokenHandler.CanReadToken(securityToken);
        }

        public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters,
            out SecurityToken validatedToken)
        {
            //How to access HttpContext/IP address from here?
            var httpContext = _httpContextAccessor.HttpContext;

            var xx = httpContext.Connection.RemoteIpAddress;
//simple condition for testing
            var yy = xx.ToString()=="::1";
            if (yy)
            { 
                validatedToken=null;
                return  null;
            }
            var principal = _tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken);

            return principal;
        }
    }
}

这里是控制器:

 [HttpGet]
        [Authorize]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            var r= Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToList();
            r.Add(new WeatherForecast(){Date =DateTime.Now,TemperatureC =111111,Summary = $"{HttpContext.User.Identity.IsAuthenticated}"});

            return r;
        }

期望发送未经授权的结果,而是发送数据。

HttpContext.User.Identity.IsAuthenticatedfalse 但仍然显示数据。

【问题讨论】:

  • 如果您使用身份,您不妨使用 SignInManager 类来检查经过身份验证的用户。
  • 他正在使用 Jwt 身份验证。

标签: c# .net asp.net-core blazor


【解决方案1】:

aut&auth的中间件需要稍后配置:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  // not here 
  //   app.UseAuthentication();
  //  app.UseAuthorization(); 
    app.UseResponseCompression();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBlazorDebugging();
    }

    app.UseCors(_myAllowSpecificOrigins);
    app.UseStaticFiles();
    app.UseClientSideBlazorFiles<Client.Startup>();

    app.UseRouting();

  // but here 
    app.UseAuthentication();
    app.UseAuthorization(); 

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
        endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
    });
}

它们必须添加到路由下方(在之后执行)。

【讨论】:

  • 是的,这对的位置是错误的,但这并不代表这个问题就在那里。
  • 我没有测试 OP 的其余代码,但将它们放在首位确实可以解释我们所知道的一种症状。
【解决方案2】:

也许你需要这样的东西:

services.AddMvcCore(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2019-11-23
    • 2019-04-19
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 2020-09-23
    相关资源
    最近更新 更多