lwl1569  

准备工作:

  1. 依赖项:Microsoft.AspNetCore.Authentication.JwtBearer
    用于创建Jwt密匙和发布信息,放在appsetting.json中,注入依赖IConfiguration时选择Microsoft.Extensions.Configuration
  2. 依赖项:Microsoft.AspNetCore.Identity.EntityFrameworkCore
    用于身份认证,获取用户等identity操作。框架内包含signInManager、userManager
  3. 使用方法:
  4. 首先先要创建用户类,我们选择继承identity.EntityFrameworkCore提供的IdentityUser类创建新的用户类,该用户类下以Address作为标记,绑定购物车、订单、角色集合,后续还会添加Token等信息
   public class ApplicationUser : IdentityUser
    {
        public string Address { get; set; }
        public ShoppingCart ShoppingCart { get; set; }
        public ICollection<Order> Orders { get; set; }

        public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
    }
  1. 之后创建JwtHelper类,通过identity框架获取用户信息并为之创建Token
   public static class JwtHelper
    {
        public static async Task<string> JwtCreaterAsync(UserManager<ApplicationUser> _userManager, IConfiguration _configuration, ApplicationUser user)//此处的model类型可以更换
        {
            // 2 创建jwt
            // header
            // payload
            var claims = new List<Claim>
            {
                // sub
                new Claim(JwtRegisteredClaimNames.Sub, user.Id),
                //new Claim(ClaimTypes.Role, "Admin")
            };
            var roleNames = await _userManager.GetRolesAsync(user);
            foreach (var roleName in roleNames)
            {
                var roleClaim = new Claim(ClaimTypes.Role, roleName);
                claims.Add(roleClaim);
            }
            // signiture
            var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"])),SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: _configuration["Authentication:Issuer"],
                audience: _configuration["Authentication:Audience"],
                claims,
                notBefore: DateTime.UtcNow,
                expires: DateTime.UtcNow.AddDays(1),
                signingCredentials
            );

            var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
            return tokenStr;
        }
    }

Appsetting中的信息如下:
{"Authentication": {"SecretKey": "suibianzifuchaun","Issuer": "fakexiecheng.com","Audience": "fakexiecheng.com"}}
3. 登录和注册需要用到的两个操作
①验证用户和密码:

            // 1 验证用户名密码
            var loginResult = await _signInManager.PasswordSignInAsync(
                loginDto.Email,
                loginDto.Password,
                false,
                false
            );
            if(!loginResult.Succeeded)
            {
                return BadRequest();
            }
            //通过email或者其他string获取对应的用户
            var user = await _userManager.FindByNameAsync(loginDto.Email);

②创建用户对象并存储

           // 1 使用用户名创建用户对象
            var user = new ApplicationUser()
            {
                UserName = registerDto.Email,
                Email = registerDto.Email
            };

            // 2 hash密码,保存用户
            var result = await _userManager.CreateAsync(user, registerDto.Password);//此处用的identityEntityFreamwork的认证框架,对于密码有要求:必须超过6位、必须带大写字符、小写字符、数字、特殊字符
            if(!result.Succeeded)
            {
                return BadRequest();
            }
            // 4 return
            return Ok();
  1. 完整的登录和注册方法代码:
using FakeXiecheng.API.Dtos;
using FakeXiecheng.API.Helper;
using FakeXiecheng.API.Models;
using FakeXiecheng.API.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
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;

namespace FakeXiecheng.API.Controllers
{
    [ApiController]
    [Route("auth")]
    public class AuthenticateController : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly ITouristRouteRepository _touristRouteRepository;

        public AuthenticateController(
            IConfiguration configuration,
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            ITouristRouteRepository touristRouteRepository
        )
        {
            _configuration = configuration;
            _userManager = userManager;
            _signInManager = signInManager;
            _touristRouteRepository = touristRouteRepository;
        }

        [AllowAnonymous]
        [HttpPost("login")]
        public async Task<IActionResult> Login([FromBody] LoginDto loginDto)
        {
            // 1 验证用户名密码
            var loginResult = await _signInManager.PasswordSignInAsync(
                loginDto.Email,
                loginDto.Password,
                false,
                false
            );
            if(!loginResult.Succeeded)
            {
                return BadRequest();
            }

            var user = await _userManager.FindByNameAsync(loginDto.Email);

            var tokenStr = await JwtHelper.JwtCreaterAsync(_userManager, _configuration, user);

            // 3 return 200 ok + jwt
            return Ok(tokenStr);
        }

        [AllowAnonymous]
        [HttpPost("register")]
        public async Task<IActionResult> Register([FromBody] RegisterDto registerDto)
        {
            // 1 使用用户名创建用户对象
            var user = new ApplicationUser()
            {
                UserName = registerDto.Email,
                Email = registerDto.Email
            };

            // 2 hash密码,保存用户
            var result = await _userManager.CreateAsync(user, registerDto.Password);
            if(!result.Succeeded)
            {
                return BadRequest();
            }

            // 3 初始化购物车
            var shoppingCart = new ShoppingCart()
            {
                Id = Guid.NewGuid(),
                UserId = user.Id
            };
            await _touristRouteRepository.CreateShoppingCart(shoppingCart);
            await _touristRouteRepository.SaveAsync();

            // 4 return
            return Ok();
        }
    }
}
  1. 服务注入(全程在Startup中)
    1、注入Jwt的认证服务
                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    byte[] secretByte = Encoding.UTF8.GetBytes(Configuration["Authentication:SecretKey"]);
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = true,//验证发布者
                        ValidIssuer = Configuration["Authentication:Issuer"],

                        ValidateAudience = true,//验证Token持有者
                        ValidAudience = Configuration["Authentication:Audience"],

                        ValidateLifetime = true,//验证是否过期

                        IssuerSigningKey = new SymmetricSecurityKey(secretByte)//传入私钥并加密
                    };
                });

2、启动用户授权框架

        {
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();//这三部的顺序不能变
            app.UseEndpoints(endpoints =>endpoints.MapControllers());//route路径,与认证无关,附此代码是为了确保启动框架顺序正确
        }
posted on 2021-10-11 13:08  lwl1569  阅读(391)  评论(0编辑  收藏  举报