我想将JWT与ASP.NET Core 2.1和MSSQL一起使用。我从互联网上找到了实现目标的有用代码。让我分享有关该项目的全部细节。它工作正常,但使用IdentityUser struct(Microsoft.AspNetCore.Identity类)。 我想使用自定义用户表的模型而不是Identity类。因为根据我发现的示例:我们创建了Migration.cs文件,然后通过写'update来更新数据库。 -database”,位于软件包管理器控制台中。此操作将在MSSQL数据库中创建许多表:AspNetRoleClaims,AspNetRoles,AspNetUserClaims,AspNetUserLogins,AspNetUserRoles,AspNetUsers,AspNetUserTokens。我不想使用它们。
MyTestDatabase
,我的“自定义用户”表名称为MyUserTable
这是MyUserTable的字段:
我创建了一个名为“ Data”的目录。我已经在该目录中创建了ApplicationDbContext.cs
文件。
这是ApplicationDbContext.cs
文件:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace JwtAuthentication.Data
{
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
#region Seed Data
builder.Entity<IdentityRole>().HasData
(
new { Id = "1", Name = "Admin", NormalizedName = "ADMIN"},
new { Id = "2", Name = "Customer", NormalizedName = "CUSTOMER" }
);
#endregion
}
}
}
我已经在根目录中创建了另一个名为ViewModels
的目录。我已经在此LoginViewModel.cs
目录中创建了RegisterViewModel.cs
和ViewModels
文件。
这是LoginViewModel.cs
文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace JwtAuthentication.ViewModels
{
public class LoginViewModel
{
public string Username { get; set; }
public string Password { get; set; }
}
}
这是RegisterViewModel.cs
文件:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace JwtAuthentication.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
}
这是appsettings.json
文件:
{
"ConnectionStrings": {
"DefaultConnection": "data source=****;initial catalog=myTestDatabase;persist security info=True;user id=sa;password=*****;MultipleActiveResultSets=True"
},
"Jwt": {
"Site": "http://www.security.org",
"SigningKey": "HelpMeHelpMeHelpMeHelpMeHelpMe",
"ExpiryInMinutes": "60"
},
"Logging":
{
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
我已经创建了控制器文件:AuthController.cs
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using JwtAuthentication.ViewModels;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
namespace JwtAuthentication.Controllers
{
public class AuthController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IConfiguration _configuration;
public AuthController(UserManager<IdentityUser> userManager, IConfiguration configuration)
{
_userManager = userManager;
_configuration = configuration;
}
//public IActionResult Index()
//{
// return View();
//}
[Route("login")]
[HttpPost]
public async Task<ActionResult> Login([FromBody] LoginViewModel model)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
#region if scope
var claim = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName)
};
var signinKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SigningKey"]));
int expiryInMinutes = Convert.ToInt32(_configuration["Jwt:ExpiryInMinutes"]);
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Site"],
audience: _configuration["Jwt:Site"],
expires: DateTime.UtcNow.AddMinutes(expiryInMinutes),
signingCredentials: new SigningCredentials(signinKey, SecurityAlgorithms.HmacSha256)
);
return Ok(
new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
}
);
#endregion
}
return Unauthorized();
}
[Route("register")]
[HttpPost]
public async Task<ActionResult> InsertUser([FromBody] RegisterViewModel model)
{
var user = new IdentityUser
{
Email = model.Email,
UserName = model.Email,
SecurityStamp = Guid.NewGuid().ToString()
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await _userManager.AddToRoleAsync(user, "Customer");
}
return Ok(new { Username = user.UserName });
}
}
}
这是Startup.cs
文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JwtAuthentication.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace JwtAuthentication
{
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>(option => option.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>(
option =>
{
option.Password.RequireDigit = false;
option.Password.RequiredLength = 6;
option.Password.RequireNonAlphanumeric = false;
option.Password.RequireUppercase = false;
option.Password.RequireLowercase = false;
}
).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
services.AddAuthentication(
option => {
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}
).AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["Jwt:Site"],
ValidIssuer = Configuration["Jwt:Site"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SigningKey"]))
};
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// 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();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}
}
这是ValuesController.cs
文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace JwtAuthentication.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
我想使用自定义用户表的Model而不是Identity类。我试图使用MyUserTable模型。但是我无法完成。