Asp.net core 如何将已授权的用户重定向回identity server 4.NET CORE中的上一页?
下面是在身份验证服务器和客户端计算机中添加的代码 如果需要更多信息,请发表评论 StartUp.cs--身份验证服务器Asp.net core 如何将已授权的用户重定向回identity server 4.NET CORE中的上一页?,asp.net-core,.net-core,asp.net-core-mvc,identityserver4,Asp.net Core,.net Core,Asp.net Core Mvc,Identityserver4,下面是在身份验证服务器和客户端计算机中添加的代码 如果需要更多信息,请发表评论 StartUp.cs--身份验证服务器 public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); var builder = services.AddIdentityServer(options => {
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var builder = services.AddIdentityServer(options =>
{
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
/*.AddProfileService<ProfileService>()*/;
builder.AddDeveloperSigningCredential();
services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
//services.AddTransient<IProfileService, ProfileService>();
}
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
try
{
UserInfo user = await GetUserDetails(context.UserName, context.Password).ConfigureAwait(false);
if (user != null && string.IsNullOrEmpty(user.ErrorMessage))
{
//set the result
context.Result = new GrantValidationResult(
subject: user.UserId.ToString(),
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, user.ErrorMessage);
return;
}
catch (Exception ex)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
}
}
//build claims array from user data
public static Claim[] GetUserClaims(UserInfo user)
{
return new Claim[]
{
new Claim("user_id", user.UserId.ToString() ?? ""),
new Claim(JwtClaimTypes.Name, (!string.IsNullOrEmpty(user.FirstName) && !string.IsNullOrEmpty(user.Surname)) ? (user.FirstName + " " + user.Surname) : ""),
new Claim(JwtClaimTypes.GivenName, user.FirstName ?? ""),
new Claim(JwtClaimTypes.FamilyName, user.Surname ?? ""),
new Claim(JwtClaimTypes.Email, user.Email ?? "")
};
}
}
ResourceOwnerPasswordValidator.cs——身份验证服务器
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var builder = services.AddIdentityServer(options =>
{
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
/*.AddProfileService<ProfileService>()*/;
builder.AddDeveloperSigningCredential();
services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
//services.AddTransient<IProfileService, ProfileService>();
}
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
try
{
UserInfo user = await GetUserDetails(context.UserName, context.Password).ConfigureAwait(false);
if (user != null && string.IsNullOrEmpty(user.ErrorMessage))
{
//set the result
context.Result = new GrantValidationResult(
subject: user.UserId.ToString(),
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, user.ErrorMessage);
return;
}
catch (Exception ex)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
}
}
//build claims array from user data
public static Claim[] GetUserClaims(UserInfo user)
{
return new Claim[]
{
new Claim("user_id", user.UserId.ToString() ?? ""),
new Claim(JwtClaimTypes.Name, (!string.IsNullOrEmpty(user.FirstName) && !string.IsNullOrEmpty(user.Surname)) ? (user.FirstName + " " + user.Surname) : ""),
new Claim(JwtClaimTypes.GivenName, user.FirstName ?? ""),
new Claim(JwtClaimTypes.FamilyName, user.Surname ?? ""),
new Claim(JwtClaimTypes.Email, user.Email ?? "")
};
}
}
登录逻辑---
[HttpPost]
[ValidateAntiForgeryToken]
公共异步任务登录(LoginInputModel模型,字符串按钮)
{
//检查我们是否在授权请求的上下文中
var context=await\u interaction.GetAuthorizationContextAsync(model.ReturnUrl);
如果(按钮==“重置”)
{
返回重定向(“ResetPasswordWithoutCode”);
}
其他的
{
//用户单击了“取消”按钮
如果(按钮==“取消”)
{
if(上下文!=null)
{
//如果用户取消,则将结果发送回IdentityServer,就像他们
//拒绝同意(即使该客户不需要同意)。
//这将向客户端发回拒绝访问的OIDC错误响应。
wait_interaction.DenyAuthorizationAsync(上下文,AuthorizationError.AccessDenied);
//我们可以信任model.ReturnUrl,因为GetAuthorizationContextAsync返回了非null
if(context.IsNativeClient())
{
//客户端是本机的,因此此更改将
//返回的响应是为最终用户提供更好的用户体验。
返回此.LoadingPage(“重定向”,model.ReturnUrl);
}
返回重定向(model.ReturnUrl);
}
其他的
{
//因为我们没有有效的上下文,所以我们只需返回主页
返回重定向(“~/”);
}
}
if(ModelState.IsValid)
{
ResourceOwnerPasswordValidationContext context1=新ResourceOwnerPasswordValidationContext();
context1.UserName=model.UserName;
context1.Password=model.Password;
//根据内存存储验证用户名/密码
wait_resourceOwner.ValidateAsync(context1);
if(context1.Result.Subject!=null&&context1.Result.Subject.Identity.IsAuthenticated)
{
var user=await ResourceOwnerPasswordValidator.GetUserDetails(model.Username,model.Password).ConfigureAwait(false);
wait_events.RaiseAsync(新的userloginsAccessEvent(user.Username,user.UserId,user.Username,clientId:context?.Client.clientId));
//仅当用户选择“记住我”时才在此处设置显式过期。
//否则,我们依赖于cookie中间件中配置的过期。
AuthenticationProperties props=null;
if(AccountOptions.AllowRememberLogin&&model.RememberLogin)
{
props=新的AuthenticationProperties
{
ispersist=true,
ExpiresUtc=DateTimeOffset.UtcNow.Add(AccountOptions.rememberLoginDuration)
};
};
//发出具有主题ID和用户名的身份验证cookie
var isuser=new IdentityServerUser(user.UserId)
{
DisplayName=user.Username
};
等待HttpContext.SignInAsync(isuser,props);
if(上下文!=null)
{
if(context.IsNativeClient())
{
//客户端是本机的,因此此更改将
//返回的响应是为最终用户提供更好的用户体验。
返回此.LoadingPage(“重定向”,model.ReturnUrl);
}
//我们可以信任model.ReturnUrl,因为GetAuthorizationContextAsync返回了非null
返回重定向(model.ReturnUrl);
}
//请求本地页面
if(Url.IsLocalUrl(model.ReturnUrl))
{
返回重定向(model.ReturnUrl);
}
else if(string.IsNullOrEmpty(model.ReturnUrl))
{
返回重定向(“~/”);
}
其他的
{
//用户可能单击了恶意链接-应记录
抛出新异常(“无效返回URL”);
}
}
wait_events.RaiseAsync(新用户登录失败事件(model.Username,“无效凭据”,clientId:context?.Client.clientId));
ModelState.AddModelError(string.Empty,AccountOptions.InvalidCredentialsErrorMessage);
}
//出了问题,用错误显示表单
var vm=等待BuildLoginViewModelAsync(模型);
返回视图(vm);
}
}
我正在调用一个webapi来检查凭据,并返回有关用户的信息,如名字和姓氏
重定向URI-https://localhost:44356/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DTestIdpApp%26redirect_uri%3Dhttps%253A%252F%252Flocalhost%253A44335%252Fsignin-oidc%26响应类型%3Dcode%26范围%3Dopenid%2520配置文件%26代码挑战%3DLEZALWC8SHZZ6LGUSDEUPR974CLSUSYVPXDNMBWOE%26代码挑战方法%3DS256%26响应模式%3Dform_post%26当前值%3D637360236231259886.mmixnjlhodmtztjhy00yzuzltliyjmtzwjmzm3zjrim2vlzm
if (this.User.Identity.IsAuthenticated)
{
return Redirect(returnUrl);
}