对于我的后端,我只希望允许通过“秘密” URL访问登录页面,否则只需将用户重定向到Webui应用即可。 为此,我创建了以下中间件和实现。
MiddleWare
namespace App.Middleware
{
public class DefaultRedirectRequest
{
private readonly RequestDelegate _next;
private readonly IIdentityServerService _identityServerService;
public DefaultRedirectRequest(RequestDelegate next, IIdentityServerService identityServerService)
{
_next = next;
_identityServerService = identityServerService;
}
public async Task InvokeAsync(HttpContext context)
{
var request = context.Request;
var response = context.Response;
var user = context.User.Identity;
if (!user.IsAuthenticated)
{
// if the Request comes from base (this App)
if (request.Headers[HeaderNames.Origin].Count == 0)
{
if (request.Path.StartsWithSegments(new PathString("/secreturl")))
{
await _next(context);
// Create url and redirect
response.Headers[HeaderNames.Location] = _identityServerService.CreateAuthorizeUrl();
response.StatusCode = StatusCodes.Status302Found;
response.Redirect(response.Headers[HeaderNames.Location]);
}
else if (request.Path.StartsWithSegments(new PathString("/signin-oidc")))
{
// Sign-in..
}
else
{
// Redirect to client app
response.Headers[HeaderNames.Location] = "http://localhost:5555";
response.StatusCode = StatusCodes.Status301MovedPermanently;
response.Redirect(response.Headers[HeaderNames.Location]);
}
}
}
else
{
await context.ChallengeAsync();
}
}
}
public static class DefaultRedirectRequestExtension
{
public static IApplicationBuilder UseDefaultRedirectRequest(this IApplicationBuilder builder)
{
return builder.UseMiddleware<DefaultRedirectRequest>();
}
}
}
IdentityServerService
public class IdentityServerService : IIdentityServerService
{
public HttpClient Client { get; }
public IdentityServerService(HttpClient client)
{
client.BaseAddress = new Uri("http://localhost:5000/");
Client = client;
}
public string CreateAuthorizeUrl()
{
var request = new RequestUrl(Client.BaseAddress.AbsoluteUri + "connect/authorize");
var url= request.CreateAuthorizeUrl(
clientId: "client.id",
responseType: "code id_token",
responseMode: "form_post",
redirectUri: "http://localhost:4444/signin-oidc",
state: Guid.NewGuid().ToString("N"),
nonce: Guid.NewGuid().ToString("N"),
scope: "openid profile roles offline_access");
return url;
}
}
启动
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<IIdentityServerService, IdentityServerService>();
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.SlidingExpiration = true;
})
.AddOpenIdConnect(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.ClientId = "client.id";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.Scope.Add("api1");
options.Scope.Add("offline_access");
options.Scope.Add("profile");
options.Scope.Add("roles");
options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Events.OnAuthorizationCodeReceived = async context =>
{
// Handle Here?
};
})
}
public void Configure(IApplicationBuilder app)
{
app.UseDefaultRedirectRequest();
app.UseAuthentication();
// static files, mvc etc..
}
通过这个,我被重定向到所有Urls上的客户端应用程序,而“秘密”版本将我定向到idsrver。到目前为止一切都很好。 我可以登录到idsrver,但在重定向回时,我只是在控制台中收到此错误消息
info: Microsoft.AspNetCore.Server.Kestrel[32]
Connection id "0HLO6R5VCNBTC", Request id "0HLO6R5VCNBTC": the application completed without reading the entire request body.
它没有遇到任何断点,所以我使用了Fiddler进行了进一步的调试。 这是从idsrver返回的原始输出。
HTTP/1.1 200 OK
Date: Fri, 12 Jul 2019 15:32:53 GMT
Content-Type: text/html; charset=UTF-8
Server: Kestrel
Cache-Control: no-store, no-cache, max-age=0
Pragma: no-cache
Transfer-Encoding: chunked
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: .AspNetCore.Identity.Application=long string.. path=/; httponly
Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
X-Content-Security-Policy: default-src 'none'; script-src 'sha256-orD0/VhH8hLqrLxKHD/HUEMdwqX6/0ve7c5hspX5VJ8='
Referrer-Policy: no-referrer
6bf
<html><head><base target='_self'/></head><body><form method='post' action='http://localhost:4444/signin-oidc'><input type='hidden' name='code' value='dda3afcefd7609714c85a49723904d7b8e6bdd3063980e6fd472231cce3ccfc8' />
<input type='hidden' name='id_token' value='eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk4NDM3OUUyM0Y4MTdBMkQ1RDhGMjIwMDNGQTU5RUUyQjVFMkU1MjQiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJtRU41NGotQmVpMWRqeUlBUDZXZTRyWGk1U1EifQ.eyJuYmYiOjE1NjI5NDU1NzMsImV4cCI6MTU2Mjk0NTg3MywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoiZmVsZm9yZ2UuY29yZSIsIm5vbmNlIjoiNTUwN2EyM2ZiYTUzNDdmZDg4NzNiZDkyMTM1NzQwYTEiLCJpYXQiOjE1NjI5NDU1NzMsImNfaGFzaCI6IjZlRmVpclktSG80NjR0c2ZkRGdKRnciLCJzaWQiOiIyYTdmYzk0YmE2MTM4Mjc4ZmM0YmNmYzgwYWJjOTRlMCIsInN1YiI6ImZkNWEyZjVkLWRiY2YtNGZmMS1iYmQxLTI3ZjIwMDc0YmY4NiIsImF1dGhfdGltZSI6MTU2Mjk0NTU3MywiaWRwIjoibG9jYWwiLCJyb2xlIjpbIkFkbWluaXN0cmF0b3IiLCJGZWxmb3JnZVVzZXIiLCJGZWxmb3JnZUFkbWluaXN0cmF0b3IiXSwiYW1yIjpbInB3ZCJdfQ.l4wwJHndOaeLxQp_v7bYsoHXMbCAxjYvtCO2JT3mzfMJ6P-NSLbjI9A6yV0eO34fUwKI4uFz9TS5MYsugCS-GTT2vPSqA4uGrZsUu4QJcPsJeI9v1ljOkEC2oB-opsXWxbNvFNiXn7oMx0HUlC74gZile5eb8bc6M0qcFWAjZ5bMfiwIVwB3PSdGya7ZVPb523CgjU3nTEApS4XXEoQOdGJ0L2HU_taHcZJC8k2xUimPya2RqQbokDCfkQBPuynHhHcX661sJblGyTukxKKZO_pTESRUay1UWmnoyNy2bQXjZemTBLaNaATKPOAuHLdPT7cGnhqAeVb3l1ivo_rvWw' />
<input type='hidden' name='scope' value='openid profile roles offline_access' />
<input type='hidden' name='state' value='2c2518ebcbd540c9bfa567264a372754' />
<input type='hidden' name='session_state' value='FWpR9DfCVp2ggyGN9L-HX5sAxTpmWIxlKk9qZE5IDSw.30c9a96a37ef1dec9b19e44aba11b114' />
<noscript><button>Click to continue</button></noscript></form>
<script>window.addEventListener('load', function()
{document.forms[0].submit();});</script></body></html>
0
我有一个使用标准设置的分支,只需点击[Authorize]属性,响应看起来就类似,并且该应用处理响应。
所以我猜想启动程序(或中间件?)无法解析原始请求体? 我在这里想念什么?如何实现此流程?
答案 0 :(得分:2)
为什么不使用OnRedirectToIdentityProvider事件?
.AddOpenIdConnect("oidc", "Open Id connect", options =>
{
// This event is fired when the user is about to be redirected to the login page.
options.Events.OnRedirectToIdentityProvider = context =>
{
var validUrl = context.Request.Path.StartsWithSegments(new PathString("/secreturl"));
if (!validUrl)
{
context.Response.Redirect("http://localhost:5555");
context.HandleResponse();
}
return Task.CompletedTask;
};
答案 1 :(得分:0)
好吧,所以我认为中间件对于您要实现的目标可能有点太复杂了。
与其使用必须检查大量内容的中间件,不如创建一个基本URL来捕获未配置的每条路由:
public class CatchAllController : Controller
{
[Route("{*url}", Order = 999)]
public IActionResult CatchAll()
{
return RedirectPermanent("http://localhost:5555");
}
}
Order = 999
确保它是您的API尝试解析的最后一个url选项。在此之前,它将解析特定于IdSvr4和您的secret-url
的URL。
另一件事是您的IdSvr4的配置。您可以找到许多不同的地方当局和服务器的指针(我不知道这是什么):
options.Authority = "http://localhost:5000";
我认为您可以从此处的快速入门指南中受益: http://docs.identityserver.io/en/latest/quickstarts/0_overview.html
也许可以尝试从其中一个示例中设置服务器。