代码之家  ›  专栏  ›  技术社区  ›  Jason

Authorize属性不使用IdentityServer 4和。净核心3.1

  •  0
  • Jason  · 技术社区  · 5 年前

    我有一本书。NET Core 3.1项目使用Identity和IdentityServer 4实现资源所有者密码授予类型。我可以获得代币,没问题,但是[Authorize]属性不起作用,它只是让一切通过。需要注意的是,我的API和Identity server位于同一个项目中。从网上的评论来看,这似乎是一个中间件订单问题,但我似乎找不到一个有效的组合。我已经仔细检查过,当没有附加授权头时,端点代码仍然被命中。

    这是我的创业公司。cs文件:

    using System;
    using System.Collections.Generic;
    using IdentityServer4.Models;
    using LaunchpadSept2020.App;
    using LaunchpadSept2020.App.Repositories;
    using LaunchpadSept2020.App.Repositories.Interfaces;
    using LaunchpadSept2020.App.Seeds;
    using LaunchpadSept2020.Models.Entities;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    namespace LaunchpadSept2020.Api
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                // Set up the database
                services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"),
                    b =>
                    {
                        b.MigrationsAssembly("LaunchpadSept2020.App");
                    })
                );
    
                services.AddIdentity<User, IdentityRole>()
                    .AddEntityFrameworkStores<ApplicationDbContext>()
                    .AddDefaultTokenProviders();
    
                services.Configure<IdentityOptions>(options =>
                {
                    options.Password.RequiredLength = 6;
                    options.Password.RequireLowercase = true;
                    options.Password.RequireUppercase = true;
                    options.Password.RequireNonAlphanumeric = false;
                    options.Password.RequireDigit = true;
                });
    
                services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(options =>
                    {
                        options.ApiName = "launchpadapi";
                        options.Authority = "http://localhost:25000";
                        options.RequireHttpsMetadata = false;
                    });
    
                services.AddIdentityServer()
                    .AddOperationalStore(options =>
                    {
                        options.ConfigureDbContext = builder => builder.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"),
                            npgSqlOptions =>
                            {
                                npgSqlOptions.MigrationsAssembly("LaunchpadSept2020.App");
                            });
                    })
                    .AddInMemoryClients(Clients.Get())
                    .AddAspNetIdentity<User>()
                    .AddInMemoryIdentityResources(Resources.GetIdentityResources())
                    .AddInMemoryApiResources(Resources.GetApiResources())
                    .AddInMemoryApiScopes(Resources.GetApiScopes())
                    .AddDeveloperSigningCredential();
    
                services.AddControllers();
    
                // Add Repositories to dependency injection
                services.AddScoped<ICompanyRepository, CompanyRepository>();
                services.AddScoped<IUserRepository, UserRepository>();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env, UserManager<User> userManager, RoleManager<IdentityRole> roleManager)
            {
                // Initialize the database
                UpdateDatabase(app);
    
                // Seed data
                UserAndRoleSeeder.SeedUsersAndRoles(roleManager, userManager);
    
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                //app.UseHttpsRedirection();
                app.UseRouting();
    
                app.UseIdentityServer(); // Includes UseAuthentication
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
    
            // Update the database to the latest migrations
            private static void UpdateDatabase(IApplicationBuilder app)
            {
                using (var serviceScope = app.ApplicationServices
                     .GetRequiredService<IServiceScopeFactory>()
                     .CreateScope())
                {
                    using (var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>())
                    {
                        context.Database.Migrate();
                    }
                }
            }
        }
    
        internal class Clients
        {
            public static IEnumerable<Client> Get()
            {
                return new List<Client>
                {
                    new Client
                    {
                        ClientId = "mobile",
                        ClientName = "Mobile Client",
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                        ClientSecrets = { new Secret("MySecret".Sha256()) },
                        AllowedScopes = new List<String> { "launchpadapi.read" }
                        //AllowAccessTokensViaBrowser = true,
                        //RedirectUris = { "http://localhost:25000/signin-oidc" },
                        //PostLogoutRedirectUris = { "http://localhost:25000/signout-callback-oidc" },
                        //AllowOfflineAccess = true
                    }
                };
            }
        }
    
        internal class Resources
        {
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new[]
                {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResource
                {
                    Name = "role",
                    UserClaims = new List<string> {"role"}
                }
            };
            }
    
            public static IEnumerable<ApiResource> GetApiResources()
            {
                return new[]
                {
                new ApiResource
                {
                    Name = "launchpadapi",
                    DisplayName = "Launchpad API",
                    Description = "Allow the application to access the Launchpad API on your behalf",
                    Scopes = new List<string> { "launchpadapi.read", "launchpadapi.write"},
                    ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
                    UserClaims = new List<string> {"role"}
                }
            };
            }
    
            public static IEnumerable<ApiScope> GetApiScopes()
            {
                return new[]
                {
                    new ApiScope("launchpadapi.read", "Read Access to Launchpad API"),
                    new ApiScope("launchpadapi.write", "Write Access to Launchpad API")
                };
            }
        }
    }
    

    还有我的控制器:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using LaunchpadSept2020.App.Repositories.Interfaces;
    using LaunchpadSept2020.Models.ViewModels;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    
    namespace LaunchpadSept2020.Api.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class CompanyController : ControllerBase
        {
            private readonly ICompanyRepository _companyRepository;
    
            public CompanyController(ICompanyRepository companyRepository)
            {
                _companyRepository = companyRepository;
            }
    
            [HttpPost]
            [Authorize]
            public async Task<ActionResult<CompanyVM>> Create([FromBody] CompanyCreateVM data)
            {
                // Make sure model has all required fields
                if (!ModelState.IsValid)
                    return BadRequest("Invalid data");
    
                try
                {
                    var result = await _companyRepository.Create(data);
                    return Ok(result);
                }
                catch
                {
                    return StatusCode(500);
                }
            }
    
            [HttpGet]
            [Authorize]
            public async Task<ActionResult<List<CompanyVM>>> GetAll()
            {
                try
                {
                    var results = await _companyRepository.GetAll();
                    return Ok(results);
                }
                catch
                {
                    return StatusCode(500);
                }
            }
        }
    }
    
    0 回复  |  直到 5 年前
        1
  •  2
  •   Tore Nestenius    5 年前

    我认为一个普遍的问题是,你在同一个应用程序中混合使用IdentityServer和ASP。总的来说,我的经验是,很难知道谁在做什么,也很难完全理解。我总是建议将IdentityServer和API放在独立的服务中。只是为了清楚地区分关注点。

        2
  •  1
  •   Beyers    5 年前

    对于本地API身份验证,您需要在启动时进行以下附加配置:

    public void ConfigureServices(IServiceCollection services)
    {
      ....
      // After services.AddIdentityServer()
      services.AddLocalApiAuthentication();
    }
    

    参考请参见 docs .

    然后,您需要详细说明本地API策略,作为 Authorize API上的属性:

    [Authorize(LocalApi.PolicyName)]
    

    查看本地API example .