登录IdentityServer 4时显示404

时间:2018-07-23 22:46:51

标签: c# asp.net-core identityserver4

与许多人一样,我正在努力建立身份服务器。这是我的情况,因为我找不到合适的解决方案

  • 我有一个包含MVC客户端(.net核心2.1)的解决方案
  • 我有一个单独的解决方案,其中包含与IdentityServer相关的代码

一切似乎都可以很好地验证用户凭据,但是登录成功后我要重定向时,将导致找不到404页面。 下面的代码可提供更多信息

IdentityServer解决方案中的LoginController

    [AllowAnonymous]
    [HttpPost]
    public async Task<IActionResult> Login([FromBody]LoginDto login)
    {
        if (!ModelState.IsValid)
            return BadRequest("Missing email or password");

        try
        {
            var loginModel = Map(login);
            var user = await _loginService.LoginAsync(loginModel);

            await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));
            return Ok();
        }
        catch (UserNotFoundException)
        {
            return BadRequest("User not found");
        }
        catch (LoginFailedException)
        {
            return Unauthorized();
        }
        catch (AccountLockedOutException)
        {
            return StatusCode((int) HttpStatusCode.Forbidden);
        }
    }

    private static LoginModel Map(LoginDto login)
    {
        return new LoginModel
        {
            Email = login.Email,
            Password = login.Password,
            RememberMe = login.RememberMe
        };
    }

身份解决方案的启动类中的配置

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<IdentityServerDbContext>(options =>
        {
            options.UseSqlServer(
                Configuration.GetConnectionString("IdentityServer"));
        });

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<IdentityServerDbContext>()
            .AddDefaultTokenProviders();

        services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
            })
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())
            .AddAspNetIdentity<ApplicationUser>();

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ApiName = "Miricle.IdentityServer.Api";
            });

        services.AddMvc();

        services.AddScoped<ILoginService, LoginService>();
        services.AddScoped<IApplicationSignInManager, ApplicationSignInManager>();
        services.AddScoped<IApplicationUserManager, ApplicationUserManager>();

        services.AddCors(options =>
        {
            options.AddPolicy(CorsPolicyName, policy =>
            {
                policy.AllowAnyHeader();
                policy.AllowAnyMethod();
                policy.AllowAnyOrigin();
                policy.AllowCredentials();
            });
        });

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseIdentityServer();
        app.UseAuthentication();

        app.UseMvcWithDefaultRoute();

        app.UseCors(CorsPolicyName);
    }
}

.NET Core MVC客户端中的LoginController

public class LoginController : Controller
{
    private readonly HttpClient _httpClient;

    public LoginController(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> Index()
    {
        var model = new LoginViewModel();

        return View(model);
    }

    [HttpPost]
    [Route("/Login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login([FromForm] LoginViewModel login)
    {
        if (!ModelState.IsValid) return View("Index", login);

        _httpClient.DefaultRequestHeaders
            .Accept
            .Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:44374/api/login");

        var content = JsonConvert.SerializeObject(new LoginViewModel()
        {
            Email = login.Email,
            Password = login.Password,
            RememberMe = login.RememberMe,
        });
        request.Content = new StringContent(content, Encoding.UTF8, "application/json");

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return Redirect("/Home/Index");
    }

}

MVC客户端启动中的配置

    public void ConfigureServices(IServiceCollection services)
    {
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";

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

                options.ClientId = "Miricle.Crm.Web";
                options.ClientSecret = "secret";
                options.ResponseType = "code id_token";

                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Add("Miricle.IdentityServer.Api");
                options.Scope.Add("offline_access");
            });

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

        services.AddSingleton<HttpClient>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        services.AddCors(options =>
        {
            options.AddPolicy(CorsPolicyName, policy =>
            {
                policy.AllowAnyHeader();
                policy.AllowAnyMethod();
                policy.AllowAnyOrigin();
                policy.AllowCredentials();
            });
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseAuthentication();

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "",
                defaults: new { controller = "Login", action = "Index" });
        });

        app.UseCors(CorsPolicyName);
    }
}

我一直在努力进行这项工作已有近一周的时间,我确信这很愚蠢,但我找不到它:/

1 个答案:

答案 0 :(得分:0)

我不了解您的代码正在尝试做什么,但是从您预期目标的描述中,我希望可以看到

  • 具有通过[Authorize]属性保护的Controller或Controller方法的MVC客户端
  • 身份服务器,其中包括用于登录屏幕的控制器和视图,该屏幕在身份验证后重定向回客户端

有一个示例可以准确地说明您要执行的操作

https://identityserver4.readthedocs.io/en/release/quickstarts/3_interactive_login.html

但是如果您不想遍历示例,则可以直接转到工作代码:

https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/3_ImplicitFlowAuthentication