无法在 asp.net 核心中为身份服务器 4 启用 CORS

Posted

技术标签:

【中文标题】无法在 asp.net 核心中为身份服务器 4 启用 CORS【英文标题】:Not able to enable CORS for identity server 4 in asp.net core 【发布时间】:2017-09-06 16:58:55 【问题描述】:

好的,我已经为我的 dot net core API 添加了 CORS 策略,但不知何故,这些 CORS 策略不适用于身份服务器 4 端点。 我有以下 api 我尝试注册用户:

    [EnableCors("AllowAllCorsPolicy")]
    [Route("api/User")]
    public class UserController : Controller
    
        private readonly UserManager<ApplicationUser> _userManager;
        private IUserServices _userService;
        public UserController(UserManager<ApplicationUser> userManager, IUserServices userService)
        
            _userManager = userManager;
            _userService = userService;
        

        [HttpPost]
        public async Task<int> Post([FromBody]User userInfo)
        
            var user = new ApplicationUser  UserName = userInfo.Name, Email = userInfo.Email,
                UserTypeId = Constant.User, CustomerId = userInfo.CustomerId ;

            //Follwing 3 lines give CORS issue.
            await _userManager.AddToRoleAsync(user, Constant.User);
            var userClaim = new Claim(Constant.User, user.Email.ToString(), ClaimValueTypes.Integer);
            await _userManager.AddClaimAsync(user, userClaim);

            // var userObj = _userService.AddNewUser(userInfo);
        

现在,如果我使用上述身份服务器方法(AddToRoleAsync()AddClaimAsync()),我的客户端会出现 CORS 错误(角度应用程序在不同的服务器上运行)

但是,如果我使用自定义方法注册用户,我不会收到 CORS 错误:

            //Don't get CORS error when commented below
            //await _userManager.AddToRoleAsync(user, Constant.User);
            //var userClaim = new Claim(Constant.User, user.Email.ToString(), ClaimValueTypes.Integer);
            //await _userManager.AddClaimAsync(user, userClaim);

            //use custom method
            var userObj = _userService.AddNewUser(userInfo);

我正在为asp.net、startup.cs启用CORS:

    public void ConfigureServices(IServiceCollection services)
            
              services.AddCors(options =>
             
                options.AddPolicy("AllowAllCorsPolicy",
                    builder => builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            );
            services.AddMvc();
          


public void Configure(IApplicationBuilder app, IHostingEnvironment env,  IServiceProvider serviceProvider)
        
            app.UseCors("AllowAllCorsPolicy");
        

我什至尝试在 startup.cs 中手动添加 CORS 标头,但没有成功:

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  IServiceProvider serviceProvider)
        
            app.Use(async (context, next) =>
        
            if (context.Request.Method == "OPTIONS")
                context.Response.StatusCode = (int)HttpStatusCode.OK;

            var headers = context.Response.Headers;
            if (headers.ContainsKey("Access-Control-Allow-Origin"))
            
                headers["Access-Control-Allow-Origin"] = string.Join(",", context.Request.Headers["Referer"].Select(x => x.Substring(0, x.Length - 1)));
            
            else
            
                context.Response.Headers.Append("Access-Control-Allow-Origin", string.Join(",", context.Request.Headers["Referer"].Select(x => x.Substring(0, x.Length - 1))));
            
            if (headers.ContainsKey("Access-Control-Allow-Headers"))
            
                headers["Access-Control-Allow-Headers"] = "Origin, Content-Type, Accept, Client, Authorization, X-Auth-Token, X-Requested-With";
            
            else
            
                context.Response.Headers.Append("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Client, Authorization, X-Auth-Token, X-Requested-With");
            
            if (headers.ContainsKey("Access-Control-Allow-Methods"))
            
                headers["Access-Control-Allow-Credentials"] = "GET, POST, PATCH, PUT, DELETE, OPTIONS";
            
            else
            
                context.Response.Headers.Append("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
            
            if (headers.ContainsKey("Access-Control-Allow-Credentials"))
            
                headers["Access-Control-Allow-Credentials"] = "true";
            
            else
            
                context.Response.Headers.Append("Access-Control-Allow-Credentials", "true");
            
            context.Response.Headers.Append("Access-Control-Expose-Headers", "X-Auth-Token");
            context.Response.Headers.Append("Vary", "Origin");
            await next();
        );
        

我看到 this documentation 用于 CORS 的身份服务器选项以及 this CORS 文档,但没有多大帮助。

【问题讨论】:

你为什么不使用app.UseIdentityServerservices.AddIdentityServer 您的身份服务器客户端定义正确吗? 【参考方案1】:

这适用于较新版本的服务器。

    services.AddSingleton<ICorsPolicyService>((container) => 
        var logger = container.GetRequiredService<ILogger<DefaultCorsPolicyService>>();
        return new DefaultCorsPolicyService(logger)
        
            AllowAll = true
        ;
    );

更多细节在此讨论中,感谢原作者

https://github.com/IdentityServer/IdentityServer4/issues/4685

【讨论】:

我遇到了这个问题,但奇怪的是只在移动设备上(用勇敢和 ff 测试)..这对我来说已经解决了!【参考方案2】:

如果您使用 IdentityServer 4 和客户端进行身份验证,您必须使用 IdentityServer 4 配置 CORS,请参阅:IdentityServer4CORS

IdentityServer4 CORS 仅用于令牌端点。 您所做的是为所有控制器/方法配置 CORS,这在您的情况下可能是正确的。但是,如果您不在 identityserver4 上启用 CORS,您将无法检索令牌。

您可以向将添加到身份服务器数据库的客户端添加允许的 CORS 列表,也可以像这样添加全局默认值:

var cors = new DefaultCorsPolicyService(_loggerFactory.CreateLogger<DefaultCorsPolicyService>())

    AllowedOrigins =  "https://foo", "https://bar" 
;
services.AddSingleton<ICorsPolicyService>(cors);

请注意,您也可以手动将其添加到数据库中。

【讨论】:

好的,如何在 .net core 3.0 中做到这一点? _loggerFactory.CreateLogger 不再支持 @ТарасКрасниця 似乎支持:docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/… 我的意思是你不能在 core 3.0 的方法 ConfigureServices 中添加 ILoggerFactory public void ConfigureServices(IServiceCollection services, ILoggerFactory loggerFactory) 在 ASP.NET Core 3.0 及更高版本中,不再可以注入 ILogger Startup.cs 和 Program.cs。有关详细信息,请参阅link。我已经找到了解决方案 services.AddSingleton(); @ТарасКрасниця,您能否详细了解一下您的解决方案。我得到了 AddSingleton 部分,但你是如何实现 CustomCorsPolicyService 的?谢谢。 @ТарасКрасниця Ilogger 应该像这样注入到 StartUp 构造函数中 -> public Startup(IConfiguration configuration, IWebHostEnvironment env, ILogger logger)。创建一个变量,您将能够访问它

以上是关于无法在 asp.net 核心中为身份服务器 4 启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net 中为一组 Web 请求发送身份验证标头

如何在 ASP.Net Web API 中为特定控制器启用 Windows 身份验证

将 [Authorize] 添加到控制器无法重定向到身份登录路由。 ASP.NET 核心 3.1 MVC

在 Asp.Net Core Web 应用程序中使用 EasyAuth 对 Azure 应用服务上的 AAD 进行身份验证时,无法填充 ClaimsPrincipal

ASP.NET 核心 1.0。 Bearer Token,无法访问自定义声明

ASP.NET 核心 blazor webassembly 为 Identity Server 4 Postman 测试获取令牌