核心2身份 - 获取ASPNetUsers.Id

时间:2017-10-13 11:37:27

标签: c# asp.net-identity asp.net-core-2.0

我有一个MVC应用程序我正在添加API控制器。

我通过Cookie和不记名令牌(JWT)进行身份验证和授权。对于MVC控制器,它使用cookie。对于API控制器,一个令牌。

我正在尝试将数据链接在一起,这些数据都是基于用户ID键入的。

MVC App的实现

var userid = _userManager.GetUserId(User);

返回ASPNetUsers.Id值。因此,在使用应用程序时,所有数据都会被GUID写为OwnerID。

现在在我的API控制器上,我有完全相同的代码行。

var userid = _userManager.GetUserId(User);

但是,这是返回用户名而不是用户ID。

我需要它返回相同的值,即ASPNetUsers.Id上的guid。

有什么想法吗?你可以在下面看到我一直在尝试的一些事情。

控制器

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TechsportiseOnline.Data;
using TechsportiseOnline.Helpers;
using TechsportiseOnline.Models;

namespace TechsportiseOnline.Controllers
{

    /// <summary>
    /// This class is used as an API for Races
    /// </summary>
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    [Route("api/[controller]")]
    public class RaceController : Controller
    {
        private readonly ApplicationDbContext _context;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly IAuthorizationService _authorizationService;
        private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(User);

        public RaceController(ApplicationDbContext context, IAuthorizationService authorizationService,
           UserManager<ApplicationUser> userManager)
        {
            _context = context;
            _userManager = userManager;
            _authorizationService = authorizationService;


        }
    /// <summary>
    /// Get all Races
    /// </summary>
    /// <remarks>
    /// Gets all Races which have been created by the user
    /// </remarks>
    /// <returns>All created Races</returns>

    [HttpGet]
    public IEnumerable<Race> GetAll()
    {
        var test = User.Identity.IsAuthenticated;
        var userid = _userManager.GetUserId(User);
        var user = GetCurrentUserAsync();

        //Get only records where the OwnerId is not the logged in User.

        //return _context.Races.Where(p => p.OwnerID == User.GetUserId()).ToList();
        return _context.Races.ToList();
    }

    /// <summary>
    /// Get a single Race
    /// </summary>
    /// <remarks>
    /// Gets the details from a single Race from it's ID
    /// </remarks>
    /// <param name="id">Race ID</param>
    /// <returns>Single Race</returns>
    [HttpGet("{id}", Name = "GetRace")]
    public IActionResult GetById(long id)
    {
        //Only return the data when it is owned by the same Id
        //var item = _context.Races.Where(p => p.OwnerID == User.GetUserId()).FirstOrDefault(t => t.ID == id);
        var item = _context.Races.FirstOrDefault(t => t.ID == id);

        if (item == null)
        {
            return NotFound();
        }

        return new ObjectResult(item);
    }

    /// <summary>
    /// Get all entries for a Race
    /// </summary>
    /// <remarks>
    /// Gets the all the entries from the race ID
    /// </remarks>
    /// <param name="id">Race ID</param>
    /// <returns>All Entries from the given Race ID</returns>
    [HttpGet("{id}/entries", Name = "GetEntriesByRaceID")]
    public IEnumerable<RaceEntry> GetAllEntries(long id)
    {
        //Only return the data when it is owned by the same Id
        //Get only records where the OwnerId is not the logged in User.
        return _context.RaceEntries
        //return _context.RaceEntries.Where(p => p.OwnerID == User.GetUserId())
                                    .Where(p => p.RaceID == id)
                                    .ToList();
    }



    ///// <summary>
    ///// Get all timings for a Race
    ///// </summary>
    ///// <remarks>
    ///// Gets the all the timings from the race ID
    ///// </remarks>
    ///// <param name="id">Race ID</param>
    ///// <returns>All timings from the given Race ID</returns>
    //[HttpGet("{id}/timings", Name = "GetTimingsByRaceID")]
    //public IEnumerable<Timing> GetAllTimings(long id)
    //{

    //    //Only return the data when it is owned by the same Id
    //    //Get only records where the OwnerId is not the logged in User.
    //    return _context.Timings.Where(p => p.OwnerId == User.GetUserId())
    //                                .Where(p => p.RaceId == id)
    //                                .ToList();
    //}

    ///// <summary>
    ///// Get the results for a Race
    ///// </summary>
    ///// <remarks>
    ///// Gets the all the results from the race ID
    ///// </remarks>
    ///// <param name="id">Race ID</param>
    ///// <returns>All results from the given Race ID</returns>
    //[HttpGet("{id}/results", Name = "GetResultsByRaceID")]
    //public IEnumerable<Results> GetAllResults(long id)
    //{
    //    List<Results> raceresults = new List<Results>();
    //    var raceid = id;

    //    foreach (var raceentry in _context.RaceEntries.Where(p => p.OwnerId == User.GetUserId())
    //                                                    .Where(p => p.RaceID == id))
    //    {
    //        var raceresult = new Results();
    //        var racedetails = _context.Races.Where(t => t.OwnerId == User.GetUserId())
    //                                            .FirstOrDefault(t => t.Id == raceid);
    //        var timingdetails = _context.Timings.Where(t => t.OwnerId == User.GetUserId())
    //                                                .FirstOrDefault(t => t.BibNumber == raceentry.BibNumber);

    //        var race = _context.Races.Where(t => t.OwnerId == User.GetUserId())
    //                             .FirstOrDefault(t => t.Id == id);


    //        raceresult.AthleteUserID = raceentry.AthleteUserId;
    //        raceresult.Category = "Category";
    //        raceresult.CategoryPosition = 1;
    //        raceresult.ChipTime = DateTime.Now; //timingdetails.EndTime - timingdetails.StartTime;
    //        raceresult.Club = raceentry.Club;
    //        raceresult.ClubPosition = 1;
    //        raceresult.EntryId = raceentry.Id;
    //        raceresult.FirstName = raceentry.FirstName;
    //        raceresult.Gender = raceentry.Gender;
    //        raceresult.GenderPosition = 1;
    //        raceresult.GunTime = DateTime.Now; //race.RaceStartTime - timingdetails.EndTime;
    //        raceresult.LastName = raceentry.LastName;
    //        raceresult.OverallPosition = 0;
    //        raceresult.RaceDate = race.RaceDate;
    //        raceresult.RaceID = raceid;
    //        raceresult.RaceName = race.Name;
    //        raceresult.ResultId = 1;
    //        raceresult.Team = raceentry.Team;
    //        raceresult.TeamPosition = 1;
    //        raceresults.Add(raceresult);
    //        //build result object
    //    }
    //    //Only return the data when it is owned by the same Id
    //    //Get only records where the OwnerId is not the logged in User.
    //    return raceresults.ToList();
    //}

    ///// <summary>
    ///// Publish the results of a Race
    ///// </summary>
    ///// <remarks>
    ///// Publishes the results as Provisional or Final. Final will submit them to RunBritain/PO10
    ///// </remarks>
    ///// <returns>The JSON for the created Race</returns>
    //[HttpPost("{id}/publish", Name = "PublishResults")]
    //public IActionResult Publish([FromBody] Race item)
    //{
    //    if (item == null)
    //    {
    //        return BadRequest();
    //    }

    //    _context.Races.Add(item);

    //    //Set Owner ID
    //    item.OwnerId = User.GetUserId();

    //    _context.SaveChanges();

    //    return CreatedAtRoute("GetRace", new { id = item.Id }, item);
    //}

    /// <summary>
    /// Creates a Race
    /// </summary>
    /// <remarks>
    /// Creates a Race which can have entrants and timings assigned to it.
    /// </remarks>
    [HttpPost]
    public IActionResult Create([FromBody] RacePost item)
    {
        if (item == null)
        {
            return BadRequest();
        }

        if (item.Name == null)
        {
            return BadRequest("The Race must have a Name");
        }

        var raceitem = new Race
        {
            CurrentEntries = item.CurrentEntries,
            Description = item.Description,
            MaxEntries = item.MaxEntries,
            Name = item.Name,
            ContactName = item.ContactName,
            ContactEmail = item.ContactEmail,
            ContactNumber = item.ContactNumber,
            //OwnerID = User.GetUserId(),
            RaceDate = item.RaceDate,
            RaceStartTime = item.RaceStartTime,
            IsCompleted = item.IsCompleted,
            IsPublished = item.IsPublished,
            IsOpenForEntries = item.IsOpenForEntries,
            LastUpdated = DateTime.Now
        };

        _context.Races.Add(raceitem);

        _context.SaveChanges();

        return CreatedAtRoute("GetRace", new { id = raceitem.ID }, raceitem);
    }

    /// <summary>
    /// Update a Race
    /// </summary>
    /// <remarks>
    /// Update's a Race's details
    /// </remarks>
    /// <param name="id">Race ID</param>
    /// <returns>The JSON for the updated Race</returns>
    [HttpPut("{id}")]
    public IActionResult Update(long id, [FromBody] Race item)
    {
        if (item == null)
        {
            return BadRequest();
        }

        if (item.Name == null)
        {
            return BadRequest("The Race must have a Name");
        }

        //var race = _context.Races.Where(t => t.OwnerID == User.GetUserId())
        var race = _context.Races
                                 .FirstOrDefault(t => t.ID == id);
        //var race = _context.Races.FirstOrDefault(t => t.ID == id);
        if (race == null)
        {
            return NotFound();
        }

        //race.OwnerID = User.GetUserId();
        race.Name = item.Name;
        race.ContactName = item.ContactName;
        race.ContactEmail = item.ContactEmail;
        race.ContactNumber = item.ContactNumber;
        race.RaceDate = item.RaceDate;
        race.RaceStartTime = item.RaceStartTime;
        race.Description = item.Description;
        race.MaxEntries = item.MaxEntries;
        race.CurrentEntries = item.CurrentEntries;
        race.IsCompleted = item.IsCompleted;
        race.IsPublished = item.IsPublished;
        race.IsOpenForEntries = item.IsOpenForEntries;
        race.LastUpdated = DateTime.Now;


        _context.Races.Update(race);
        _context.SaveChanges();
        return new NoContentResult();
    }


    /// <summary>
    /// Delete a Race
    /// </summary>
    /// <remarks>
    /// Deletes a Race. Note: This will orphan any related result data and is not recommended!
    /// </remarks>
    /// <param name="id">Race ID</param>
    /// <returns></returns>
    [HttpDelete("{id}")]
    public IActionResult Delete(long id)
    {
        //var race = _context.Races.Where(p => p.OwnerID == User.GetUserId()).FirstOrDefault(t => t.ID == id);
        var race = _context.Races.FirstOrDefault(t => t.ID == id);
        //var race = _context.Races.FirstOrDefault(t => t.Id == id);

        if (race == null)
        {
            return NotFound();
        }

        var raceid = race.ID;

        ////Delete associated race entries
        //foreach (var raceentry in _context.RaceEntries.Where(p => p.OwnerId == User.GetUserId())
        //                                                .Where(p => p.RaceID == raceid))
        //{
        //    _context.RaceEntries.Remove(raceentry);
        //}

        ////Delete associated race timings
        //foreach (var timing in _context.Timings.Where(p => p.OwnerId == User.GetUserId())
        //                                                .Where(p => p.RaceId == raceid))
        //{
        //    _context.Timings.Remove(timing);
        //}

        //Delete/Save the deletion of the race
        _context.SaveChanges();
        return new NoContentResult();
    }
}

}

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TechsportiseOnline.Data;
using TechsportiseOnline.Models;
using TechsportiseOnline.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using TechsportiseOnline.Authorization;
using TechsportiseOnline.Helpers;
using Swashbuckle.AspNetCore.Swagger;
using System.IO;
using Microsoft.Extensions.PlatformAbstractions;
using static TechsportiseOnline.Helpers.Swagger;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace TechsportiseOnline
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("TechsportiseDB")));
                                                        //options.UseInMemoryDatabase("Teschsportise"));

            services.AddIdentity<ApplicationUser, IdentityRole>(config =>
                {
                    config.SignIn.RequireConfirmedEmail = true;
                })
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.Configure<IdentityOptions>(options =>
            {
                // Password settings
                options.Password.RequireDigit = true;
                options.Password.RequiredLength = 6;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
                options.Password.RequireLowercase = false;
                options.Password.RequiredUniqueChars = 2;

                // Lockout settings
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                options.Lockout.MaxFailedAccessAttempts = 10;
                options.Lockout.AllowedForNewUsers = true;

                // User settings
                options.User.RequireUniqueEmail = true;
            });

            services.Configure<AuthMessageSenderOptions>(Configuration);

            //services.ConfigureApplicationCookie(options =>
            //{
            //    // Cookie settings
            //    options.Cookie.HttpOnly = true;
            //    options.Cookie.Expiration = TimeSpan.FromDays(150);
            //    options.LoginPath = "/Account/Login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
            //    options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
            //    options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
            //    options.SlidingExpiration = true;
            //});

            // Add application services.
            services.AddTransient<IEmailSender, Email>();
            //services.AddTransient<ICreateContact>();
            //services.AddTransient<IUpdateContact>();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "Techsportise API", Version = "v1" });
                c.OperationFilter<AddRequiredHeaderParameter>();
                var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "Techsportise.xml");
                c.IncludeXmlComments(filePath);
            });

            services.Configure<JWTSettings>(Configuration.GetSection("JWTSettings"));


            services.AddAuthentication()
                .AddCookie()
                .AddJwtBearer(options =>
                {
                    options.RequireHttpsMetadata = false;
                    options.IncludeErrorDetails = true;

                    var secretKey = Configuration.GetSection("JWTSettings:SecretKey").Value;
                    var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

                    options.TokenValidationParameters = new TokenValidationParameters
                    {

                        ValidateIssuer = true,
                        ValidIssuer = Configuration.GetSection("JWTSettings:Issuer").Value,
                        ValidateAudience = true,
                        ValidAudience = Configuration.GetSection("JWTSettings:Audience").Value,
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = signingKey,

                    };
                });



             services.AddMvc();

            var skipSSL = Configuration.GetValue<bool>("LocalTest:skipSSL");
            // requires using Microsoft.AspNetCore.Mvc;
            services.Configure<MvcOptions>(options =>
            {
                // Set LocalTest:skipSSL to true to skip SSL requrement in 
                // debug mode. This is useful when not using Visual Studio.
                if (!skipSSL)
                {
                    options.Filters.Add(new RequireHttpsAttribute());
                }
            });


            //services.AddMvc(config =>
            //{
            //    var policy = new AuthorizationPolicyBuilder()
            //                     .RequireAuthenticatedUser()
            //                     .Build();
            //    config.Filters.Add(new AuthorizeFilter(policy));
            //});

            services.AddScoped<IAuthorizationHandler,
                      OwnerRaceAuthorizationHandler>();

            services.AddSingleton<IAuthorizationHandler,
                                  AdminRaceAuthorizationHandler>();

            services.AddScoped<IAuthorizationHandler,
                      OwnerRaceEntriesAuthorizationHandler>();

            services.AddSingleton<IAuthorizationHandler,
                                  AdminRaceEntriesAuthorizationHandler>();

        }

        // 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.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();


            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "Techsportise API V1");
            });


        }
    }
}

编辑:这是生成令牌的TokenController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using TechsportiseOnline.Models.AccountViewModels;
using Microsoft.AspNetCore.Identity;
using TechsportiseOnline.Models;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using TechsportiseOnline.Helpers;

namespace TechsportiseOnline.Controllers
{
    [Produces("application/json")]
    [Route("api/Token")]
    public class TokenController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IConfiguration _configuration;
        private readonly IOptions<JWTSettings> _jwtConfig;

        public TokenController(
              UserManager<ApplicationUser> userManager,
              SignInManager<ApplicationUser> signInManager,
              IConfiguration configuration,
              IOptions<JWTSettings> jwtConfig)
                    {
                        _userManager = userManager;
                        _signInManager = signInManager;
                        _configuration = configuration;
                        _jwtConfig = jwtConfig;


        }

        [AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> GenerateToken([FromBody] LoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByEmailAsync(model.Email);

                if (user != null)
                {
                    var result = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
                    if (result.Succeeded)
                    {

                        var claims = new[]
                        {
                          new Claim(JwtRegisteredClaimNames.Sub, user.Email),
                          new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                        };

                        var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_jwtConfig.Value.SecretKey.ToString()));
                        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                        var token = new JwtSecurityToken(_jwtConfig.Value.Issuer.ToString(),
                          _jwtConfig.Value.Audience.ToString(),
                          claims,
                          expires: DateTime.Now.AddDays(30),
                          signingCredentials: creds);

                       // return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });

                        return new JsonResult(new Dictionary<string, object>
                          {
                            { "access_token", new JwtSecurityTokenHandler().WriteToken(token) },
                          });
                    }
                }
            }

            return BadRequest("Could not create token");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

感谢Kirk,在他提出问题之后我能够很快看到修复程序,然后我查看了我的令牌生成器控制器。

在我的令牌中,我正在生成声明

new Claim(JwtRegisteredClaimNames.Sub, user.Email),

将其更改为

new Claim(JwtRegisteredClaimNames.Sub, user.Id),

解决了它。