这是我第一次使用ASP.NET core 2.2身份管理Controller中的授权。在客户端,我使用(Login.cshtml.cs)SignInManger.PasswordSignInAsync(…)登录用户。用户成功登录后,我将HttpClient调用发送到另一个项目中的UsersController,以获取更多用户的信息。但是,控制器未从请求中接收Claims.ClaimsPrincipal(用户)信息。 [Authorize(Roles =“ admin”)]失败,但[AllowAnonymous]通过。我检查了请求cookie。用户HttpContext未更新为客户端的已登录用户。确切地说,我不知道如何更新Cookie中的用户。我以为是在后台完成的。我浏览了许多帖子,但是没有一个帖子明确提到如何在Cookie中更新用户并发送给控制器。在程序退出Login.cshtml.cs之后,似乎已完成对用户的更新。我可以通过在Login.cshtml.cs的公共异步任务OnPostAsync(string returnUrl = null)中使用SingInManager.CreateUserPrincipalAsync(…)来获取用户的身份。但是我不知道如何将该身份传递给Cookie中的用户并将其发送给Controller。
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
// test: get the Identity of the Input.Email
var user = await _signInManager.UserManager.FindByEmailAsync(Input.Email);
var userPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
var identity = userPrincipal.Identity;
// * User Identity does not populate at this point.
var ret = await GetRestOfUserInfo();
}
}
return Page();
}
private async Task<int> GetRestOfUserInfo()
{
var userStatus = await _userManager.GetUserAsync(User);
UserCSDto userCDDto = new UserCSDto()
{
Email = Input.Email,
UserName = Input.Email,
Password = Input.Password,
RememberMe = Input.RememberMe
};
CookieContainer cookieContainer = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
{
UseCookies = true,
UseDefaultCredentials = true,
CookieContainer = cookieContainer
};
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(JsonConvert.SerializeObject(userCDDto), Encoding.UTF8, "application/json");
var url = _connectionSettings.UrlConnection + "/api/users/authenticate";
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode)
{
var respUser = JsonConvert.DeserializeObject<User>(response.Content.ReadAsStringAsync().Result);
var _responseToken = response.Headers.Where(t => t.Key == "Authorization")
.Select(t => t.Value);
var token = (_responseToken.FirstOrDefault()).FirstOrDefault();
applicationUser.PreferredName = respUser.PreferredName;
applicationUser.Token = token;
ApplicationUser user = await _userManager.FindByEmailAsync(Input.Email);
user.Token = token;
user.PreferredName = respUser.PreferredName ?? "";
IEnumerable<Claim> claims = new Claim[]
{
new Claim("Token", token),
new Claim("PreferredName", "123abc") // respUser.PreferredName)
};
await _userManager.AddClaimsAsync(user, claims);
return 1;
}
return 0;
}
[Authorize]
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class UsersController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private IUserService _userService;
public UsersController(UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
:
:
[Authorize(Roles = "any role")] // failed because User does not contain any info
[AllowAnonymous] // works because no authorization check
[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate([FromBody]UserCSDto userParam)
{
var username = User.Identity.Name; // username is null because User does not
// have info.
var user = _userService.Authenticate(userParam.UserName, userParam.Password);
if (user == null)
return BadRequest(new { message = "Username or passwrod is incorrect" });
var token = _jwtTokenService.CreateToken(userCSDto);
Response.Headers.Add("Authorization", "Bearer " + token);
Response.Headers.Add("Content-Type", "application/json");
return Ok(userCSDto);
}
:
:
}
/////////////////////////////
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.Configure<ConnectionSettings>(Configuration.GetSection("ConnectionStrings"));
var connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<EFCoreContext>(
options => options.UseSqlServer(connection,
b => b.MigrationsAssembly("EFStructures"))); // from Data project
services.AddHttpContextAccessor(); // #.Net Core 2.2
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.Expiration = TimeSpan.FromHours(1);
options.SlidingExpiration = true;
});
services.AddSession(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.Name = "Test.Session";
options.IdleTimeout = TimeSpan.FromMinutes(60);
options.Cookie.Path = "/";
});
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = true;
// Require Confirmed and Unique Email
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedEmail = false;
});
#region authenication using JWT token
services.Configure<JwtTokenSettings>(Configuration.GetSection("JwtTokenSettings"));
///// configure jwt authentication
var jwtTokenSettings = Configuration.GetSection("JwtTokenSettings").Get<JwtTokenSettings>();
var key = Encoding.ASCII.GetBytes(jwtTokenSettings.Secret);
//Adds cookie middleware to the services collection and configures it
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => options.LoginPath = new PathString("/account/login"));
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
//ValidateIssuer = Configuration["AppSettings:Issuer"],
//ValidateAudience = Configuration["AppSettings:Issuer"],
ValidateLifetime = true
};
});
#endregion
#region Add Role services to Identity RAZOR PAGE only
services.AddIdentity<ApplicationUser, IdentityRole>()
// .AddDefaultUI(Microsoft.AspNetCore.Identity.UI.UIFramework.Bootstrap4)
.AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<EFCoreContext>();
#endregion
#region Setting for using Identity
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
#endregion Setting for using Identity
services.AddHttpClient();
services.AddScoped<IJwtTokenService, JwtTokenService>();
services.AddScoped<IEmailSenderService, EmailSenderService>();
services.AddScoped<IEmailSender, EmailSender>();
#region Get EmailSettings from appsettings.json
services.AddOptions();
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
#endregion Get EmailSettings from appsettings.json
services.AddMvc()
.ConfigureApiBehaviorOptions(options =>
{
options
.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseAuthentication();
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRequestLocalization();
app.UseMvcWithDefaultRoute();
// global cors policy
app.UseCors(x => x
.WithOrigins("https://localhost")
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseMvc();
}
}