簡體   English   中英

ASP.NET Core 托管 Blazor 模板中的授權問題

[英]Authorization issue in ASP.NET Core hosted Blazor template

我在 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.IsAuthenticated給出false但仍顯示數據。

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");
    });
}

它們必須添加到路由下面(在之后執行)。

也許你需要這樣的東西:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM