• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

JWT单点登录(包含roles)

开发技术 开发技术 3小时前 2次浏览

准备工作:

  1. 依赖项:Microsoft.AspNetCore.Authentication.JwtBearer
    用于创建Jwt密匙和发布信息,放在appsetting.json中,注入依赖IConfiguration时选择Microsoft.Extensions.Configuration
    使用方法:(根据业务需要自定义创建JwtHelper类)
   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"}}
2. 依赖项:Microsoft.AspNetCore.Identity.EntityFrameworkCore
用于身份认证signInManager、userManager
验证用户和密码:

            // 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.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);

            // 2 创建jwt
            // header
            var signingAlgorithm = SecurityAlgorithms.HmacSha256;
            // 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 secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            var signingKey = new SymmetricSecurityKey(secretByte);
            var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);

            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);

            // 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 初始化,一些需要注册时运行的代码放到这里运行


            // 4 return
            return Ok();
        }
    }
}

4.服务注入(全程在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路径,与认证无关,附此代码是为了确保启动框架顺序正确
        }

程序员灯塔
转载请注明原文链接:JWT单点登录(包含roles)
喜欢 (0)