ApiController无法从HttpRequest(Razor)接收身份信息

时间:2019-03-19 17:43:11

标签: c# asp.net-core

这是我第一次使用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();
    }
}

0 个答案:

没有答案