Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# OpenID Connect允许重定向URI为空,导致;无效重定向“U uri”;关于IdentityServer 4_C#_.net 4.0_Identityserver4_Openid Connect_Owin.security - Fatal编程技术网

C# OpenID Connect允许重定向URI为空,导致;无效重定向“U uri”;关于IdentityServer 4

C# OpenID Connect允许重定向URI为空,导致;无效重定向“U uri”;关于IdentityServer 4,c#,.net-4.0,identityserver4,openid-connect,owin.security,C#,.net 4.0,Identityserver4,Openid Connect,Owin.security,我有一个运行在.NET核心项目上的IdentityServer4,我正试图使现有的.NET Framework web应用程序成为该服务器的客户端 项目正在使用Microsoft.Owin.Security,并在Startup.csI中设置身份验证设置 但是,当请求发送到IdentityServer时,AllowedRedirectUri参数只是一个空数组,因此RedirectUri参数与该空数组中的参数不匹配,导致无效重定向uri错误 以下是现有项目的Startup.cs: using Mic

我有一个运行在.NET核心项目上的IdentityServer4,我正试图使现有的.NET Framework web应用程序成为该服务器的客户端

项目正在使用
Microsoft.Owin.Security
,并在
Startup.cs
I中设置身份验证设置

但是,当请求发送到IdentityServer时,
AllowedRedirectUri
参数只是一个空数组,因此
RedirectUri
参数与该空数组中的参数不匹配,导致
无效重定向uri
错误

以下是现有项目的
Startup.cs

using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;

namespace MyProject.Services
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    RequireHttpsMetadata = false,
                    AuthenticationType = "oidc",
                    SignInAsAuthenticationType = "Cookies",
                    Authority = "http://localhost:5000",
                    RedirectUri = "http://localhost:8010/myproject.services/api/oidc",
                    PostLogoutRedirectUri = "http://localhost:8010/myproject.application",
                    ClientId = "CLIENT1",
                    ClientSecret = "a-local-testing-password",
                    Scope = "CLIENT1 offline_access",
                    ResponseType = "code id_token" 
                });
        }
    }
}
以下是从日志记录中找到的配置生成的请求:

IdentityServer4.Endpoints.AuthorizeEndpoint[0]
{
  "ClientId": "CLIENT1",
  "ClientName": "CLIENT1_name",
  "RedirectUri": "http://localhost:8010/myproject.services/api/oidc",
  "AllowedRedirectUris": [], <-- is empty, but should contain the RedirectUri
  "SubjectId": "anonymous",
  "RequestedScopes": "",
  "Raw": {
    "client_id": "CLIENT1",
    "redirect_uri": "http://localhost:8010/myproject.services/api/oidc",
    "response_mode": "form_post",
    "response_type": "code id_token",
    "scope": "openid profile",
    "state": "OpenIdConnect.AuthenticationProperties=[...]",
    "nonce": "[...]",
    "x-client-SKU": "ID_NET451",
    "x-client-ver": "5.2.1.0"
  }
}
Update2:以下是IdentityServer4的
Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MyProject.STS4.ManagementSite.Data;
using MyProject.STS4.ManagementSite.Models;
using MyProject.STS4.ManagementSite.Services;
using MyProject.STS4.ManagementSite.Tenant;
using IdentityServer4.Services;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Reflection;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.IdentityModel.Tokens;
using IdentityServer4;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Globalization;
using System.Security.Claims;
using MyProject.STS4.ManagementSite.Models.Mail;

namespace MyProject.STS4.ManagementSite
{
    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)
        {
            // Read this part of the appsettings.json and convert it into the SmtpConfig
            services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));

            string connectionString = Configuration.GetConnectionString("DefaultConnection");
            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            services.AddDbContext<ApplicationDbContext>(options =>
                 options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                 sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)
                 ));

            // Explicitly added
            //services.TryAddScoped<IUserClaimsPrincipalFactory<TenantUser>, UserClaimsPrincipalFactory<TenantUser, IdentityRole>>();

            services.AddIdentity<TenantUser, IdentityRole>(options =>
            {
                // This should send a mail when registering
                options.SignIn.RequireConfirmedEmail = false;

                options.User.RequireUniqueEmail = false;
                // Allows emails toe be used in the username
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
            })
              .AddEntityFrameworkStores<ApplicationDbContext>()
              .AddDefaultTokenProviders()
              .AddUserValidator<TenantUserValidator>(); // register our own validator

            // Add application services.
            services.AddTransient<IEmailSender, EmailSender>();

            services.AddMvc();

            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddAspNetIdentity<TenantUser>()
                // this adds the config data from DB (clients, resources)
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                // this adds the operational data from DB (codes, tokens, consents)
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));

                    // this enables automatic token cleanup. this is optional.
                    options.EnableTokenCleanup = true;
                    options.TokenCleanupInterval = 30;
                });

            // Add the possible authentication methods
            services.AddAuthentication()
                .AddGoogle("Google", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                    options.ClientId = "[...]";
                    options.ClientSecret = "[...]";
                })
                .AddOpenIdConnect("oidc", "OpenID Connect", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                    options.SignOutScheme = IdentityServerConstants.SignoutScheme;

                    options.Authority = "http://localhost:5000/";
                    options.RequireHttpsMetadata = false;
                    options.ClientId = "implicit";

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    };
                });

            // This is still to test Azure Auth
            //.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
            //{
            //  ClientId = Configuration["AzureAD:ClientId"],
            //  Authority = string.Format(CultureInfo.InvariantCulture, Configuration["AzureAd:AadInstance"], "common", "/v2.0"),
            //  ResponseType = OpenIdConnectResponseType.IdToken,

            //  Events = new OpenIdConnectEvents
            //  {                       
            //      OnTokenValidated = TokenValidated
            //  },
            //  TokenValidationParameters = new TokenValidationParameters
            //  {
            //      // Instead of using the default validation (validating against
            //      // a single issuer value, as we do in line of business apps), 
            //      // we inject our own multitenant validation logic
            //      ValidateIssuer = false,

            //      NameClaimType = "name"
            //  }
            //}
            //);

            // Registering this service allows for checking if user is active and enhancing the user with extra data (such as the claims)
            services.AddTransient<IProfileService, TenantUserProfileService>();
        }

        private Task TokenValidated(TokenValidatedContext context)
        {
            /* ---------------------
            // Replace this with your logic to validate the issuer/tenant
                ---------------------       
            // Retriever caller data from the incoming principal
            string issuer = context.SecurityToken.Issuer;
            string subject = context.SecurityToken.Subject;
            string tenantID = context.Ticket.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

            // Build a dictionary of approved tenants
            IEnumerable<string> approvedTenantIds = new List<string>
            {
                "<Your tenantID>",
                "9188040d-6c67-4c5b-b112-36a304b66dad" // MSA Tenant
            };
            o
            if (!approvedTenantIds.Contains(tenantID))
                throw new SecurityTokenValidationException();
                --------------------- */

            var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
            //add your custom claims here
            claimsIdentity.AddClaim(new Claim("test", "helloworld!!!"));

            return Task.FromResult(0);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            // this will do the initial DB population
            SeedData.EnsureSeedData(app.ApplicationServices);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            // app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
            app.UseIdentityServer();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.Builder;
使用Microsoft.AspNetCore.Identity;
使用Microsoft.EntityFrameworkCore;
使用Microsoft.AspNetCore.Hosting;
使用Microsoft.Extensions.Configuration;
使用Microsoft.Extensions.DependencyInjection;
使用MyProject.STS4.ManagementSite.Data;
使用MyProject.STS4.ManagementSite.Models;
使用MyProject.STS4.ManagementSite.Services;
使用MyProject.STS4.ManagementSite.Tenant;
使用IdentityServer 4.服务;
使用Microsoft.Extensions.DependencyInjection.Extensions;
运用系统反思;
使用IdentityServer4.EntityFramework.dbContext;
使用IdentityServer4.EntityFramework.Mappers;
使用Microsoft.IdentityModel.Tokens;
使用IdentityServer4;
使用Microsoft.AspNetCore.Authentication.OpenIdConnect;
使用Microsoft.IdentityModel.Protocols.OpenIdConnect;
利用制度全球化;
使用System.Security.Claims;
使用MyProject.STS4.ManagementSite.Models.Mail;
命名空间MyProject.STS4.ManagementSite
{
公营创业
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
//此方法由运行时调用。请使用此方法将服务添加到容器中。
public void配置服务(IServiceCollection服务)
{
//阅读appsettings.json的这部分内容,并将其转换为SmtpConfig
services.Configure(Configuration.GetSection(“Smtp”));
string connectionString=Configuration.GetConnectionString(“DefaultConnection”);
var migrationassembly=typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”),
sqlOptions=>sqlOptions.MigrationsAssembly(MigrationsAssembly)
));
//明确添加
//services.TryAddScoped();
服务.附加性(选项=>
{
//这应该在注册时发送邮件
options.SignIn.RequireConfirmedEmail=false;
options.User.RequireUniqueEmail=false;
//允许在用户名中使用电子邮件
options.User.AllowedUserNameCharacters=“abcdefghijklmnopqrstuvwxyzabefghijklmnopqrstuvwxyz012456789-.@+”;
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddUserValidator();//注册我们自己的验证器
//添加应用程序服务。
services.AddTransient();
services.AddMvc();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddAsNetIdentity()
//这将添加来自DB(客户端、资源)的配置数据
.AddConfigurationStore(选项=>
{
options.ConfigureDbContext=builder=>
builder.UseSqlServer(connectionString,
sql=>sql.migrationassembly(migrationassembly));
})
//这将添加来自DB的操作数据(代码、令牌、同意)
.addStore(选项=>
{
options.ConfigureDbContext=builder=>
builder.UseSqlServer(connectionString,
sql=>sql.migrationassembly(migrationassembly));
//这将启用自动令牌清理。这是可选的。
options.EnableTokenCleanup=true;
options.TokenCleanupInterval=30;
});
//添加可能的身份验证方法
services.AddAuthentication()
.AddGoogle(“谷歌”,选项=>
{
options.signnscheme=IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId=“[…]”;
options.ClientSecret=“[…]”;
})
.AddOpenIdConnect(“oidc”,“OpenID连接”,选项=>
{
options.signnscheme=IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme=IdentityServerConstants.SignOutScheme;
选项。权限=”http://localhost:5000/";
options.RequireHttpsMetadata=false;
options.ClientId=“隐式”;
options.TokenValidationParameters=新的TokenValidationParameters
{
NameClaimType=“name”,
RoleClaimType=“角色”
};
});
//这仍然需要测试Azure Auth
//.UseOpenIdConnectAuthentication(新的OpenIdConnectOptions
//{
//ClientId=Confi
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MyProject.STS4.ManagementSite.Data;
using MyProject.STS4.ManagementSite.Models;
using MyProject.STS4.ManagementSite.Services;
using MyProject.STS4.ManagementSite.Tenant;
using IdentityServer4.Services;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Reflection;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.IdentityModel.Tokens;
using IdentityServer4;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Globalization;
using System.Security.Claims;
using MyProject.STS4.ManagementSite.Models.Mail;

namespace MyProject.STS4.ManagementSite
{
    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)
        {
            // Read this part of the appsettings.json and convert it into the SmtpConfig
            services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));

            string connectionString = Configuration.GetConnectionString("DefaultConnection");
            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            services.AddDbContext<ApplicationDbContext>(options =>
                 options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                 sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)
                 ));

            // Explicitly added
            //services.TryAddScoped<IUserClaimsPrincipalFactory<TenantUser>, UserClaimsPrincipalFactory<TenantUser, IdentityRole>>();

            services.AddIdentity<TenantUser, IdentityRole>(options =>
            {
                // This should send a mail when registering
                options.SignIn.RequireConfirmedEmail = false;

                options.User.RequireUniqueEmail = false;
                // Allows emails toe be used in the username
                options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
            })
              .AddEntityFrameworkStores<ApplicationDbContext>()
              .AddDefaultTokenProviders()
              .AddUserValidator<TenantUserValidator>(); // register our own validator

            // Add application services.
            services.AddTransient<IEmailSender, EmailSender>();

            services.AddMvc();

            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddAspNetIdentity<TenantUser>()
                // this adds the config data from DB (clients, resources)
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                // this adds the operational data from DB (codes, tokens, consents)
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));

                    // this enables automatic token cleanup. this is optional.
                    options.EnableTokenCleanup = true;
                    options.TokenCleanupInterval = 30;
                });

            // Add the possible authentication methods
            services.AddAuthentication()
                .AddGoogle("Google", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                    options.ClientId = "[...]";
                    options.ClientSecret = "[...]";
                })
                .AddOpenIdConnect("oidc", "OpenID Connect", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                    options.SignOutScheme = IdentityServerConstants.SignoutScheme;

                    options.Authority = "http://localhost:5000/";
                    options.RequireHttpsMetadata = false;
                    options.ClientId = "implicit";

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    };
                });

            // This is still to test Azure Auth
            //.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
            //{
            //  ClientId = Configuration["AzureAD:ClientId"],
            //  Authority = string.Format(CultureInfo.InvariantCulture, Configuration["AzureAd:AadInstance"], "common", "/v2.0"),
            //  ResponseType = OpenIdConnectResponseType.IdToken,

            //  Events = new OpenIdConnectEvents
            //  {                       
            //      OnTokenValidated = TokenValidated
            //  },
            //  TokenValidationParameters = new TokenValidationParameters
            //  {
            //      // Instead of using the default validation (validating against
            //      // a single issuer value, as we do in line of business apps), 
            //      // we inject our own multitenant validation logic
            //      ValidateIssuer = false,

            //      NameClaimType = "name"
            //  }
            //}
            //);

            // Registering this service allows for checking if user is active and enhancing the user with extra data (such as the claims)
            services.AddTransient<IProfileService, TenantUserProfileService>();
        }

        private Task TokenValidated(TokenValidatedContext context)
        {
            /* ---------------------
            // Replace this with your logic to validate the issuer/tenant
                ---------------------       
            // Retriever caller data from the incoming principal
            string issuer = context.SecurityToken.Issuer;
            string subject = context.SecurityToken.Subject;
            string tenantID = context.Ticket.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

            // Build a dictionary of approved tenants
            IEnumerable<string> approvedTenantIds = new List<string>
            {
                "<Your tenantID>",
                "9188040d-6c67-4c5b-b112-36a304b66dad" // MSA Tenant
            };
            o
            if (!approvedTenantIds.Contains(tenantID))
                throw new SecurityTokenValidationException();
                --------------------- */

            var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
            //add your custom claims here
            claimsIdentity.AddClaim(new Claim("test", "helloworld!!!"));

            return Task.FromResult(0);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            // this will do the initial DB population
            SeedData.EnsureSeedData(app.ApplicationServices);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            // app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
            app.UseIdentityServer();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}