.net core jwt 实现简易授权

jwt授权拓展类AddAuth:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Siia.MobileApi.Extensions.Jwt;
using System;
using System.Text;

namespace Siia.MobileApi.Extensions
{
    public static class AuthenticationExt
    {
        public static void AddAuth(this IServiceCollection services, IConfiguration configuration)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            JwtSettings jwtSettings = new JwtSettings();
            services.Configure<JwtSettings>(configuration.GetSection("JwtSettings"));
            configuration.GetSection("JwtSettings").Bind(jwtSettings);

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(o =>
                {
                    o.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,//是否验证Issuer
                        ValidateAudience = true,//是否验证Audience
                        ValidateLifetime = true,//是否验证失效时间
                        ValidIssuer = jwtSettings.Issuer,
                        ValidAudience = jwtSettings.Audience,
                        //用于签名验证
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.SecretKey)),
                        //注意这是缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟
                        //ClockSkew = TimeSpan.FromSeconds(4)
                    };
                });
            services.AddTransient<IPassport, Passport>(PassportFactory);
        }
        private static Passport PassportFactory(IServiceProvider provider)
        {
            var httpAccessor = provider.GetService<IHttpContextAccessor>();
            if (httpAccessor == null)
            {
                return null;
            }
            return new Passport(httpAccessor.HttpContext?.User);
        }
    }
}
View Code

ConfigureServices中注入AddAuth: services.AddAuth(Configuration);

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSwagger();
            services.AddAuth(Configuration);
            services.AddScoped<IJwt, Jwt>(); // Jwt注入

            //json 序列化问题
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; //指定时间的序列化格式
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //忽略循环引用
            });

            //解决中文被编码
            services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));

            services.AddHttpClient("Siia.MobileApi");
            //防止回收
            services.AddQuartzHostedService()
                .AddQuartzJob<WeatherMonitoring>()
               .AddQuartzJob<HealthCheckJob>();

            //services.AddSingleton<MessageQueueFunc>();
        }
View Code

Configure中:

app.UseAuthentication();
app.UseAuthorization();

jwt,生成授权token:

using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Siia.MobileApi.Extensions.Jwt
{
    public class Jwt : IJwt
    {
        private JwtSettings _jwSetting = new JwtSettings();
        public Jwt(IConfiguration configration)
        {
            configration.GetSection("JwtSettings").Bind(_jwSetting);
        }
        /// <summary>
        /// 生成Token
        /// </summary>
        /// <param name="Claims"></param>
        /// <returns></returns>
        public (string token, int expires) GetToken(Dictionary<string, string> Claims)
        {
            List<Claim> claims = new List<Claim>();
            foreach (var item in Claims)
            {
                claims.Add(new Claim(item.Key, item.Value));
            }
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._jwSetting.SecretKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var expires = DateTime.Now.AddMinutes(_jwSetting.Lifetime);
            var securityToken = new JwtSecurityToken(
                issuer: this._jwSetting.Issuer,
                audience: this._jwSetting.Audience,
                claims: claims,
                expires: expires,
                signingCredentials: creds
                );
            var token = new JwtSecurityTokenHandler().WriteToken(securityToken);
            return (token, _jwSetting.Lifetime * 60);
        }

    }
}
View Code

IJwt:

public interface IJwt
    {
        (string token, int expires) GetToken(Dictionary<string, string> Claims);
    }
View Code

配置文件model:

internal class JwtSettings
    {
        public string Issuer { get; set; }
        public string Audience { get; set; }
        /// <summary>
        /// 加密key
        /// </summary>
        public string SecretKey { get; set; }
        /// <summary>
        /// 生命周期
        /// </summary>
        public int Lifetime { get; set; }
    }
View Code

appsettings.json:

"JwtSettings": {
    "Issuer": "issuer", //随意定义
    "Audience": "Audience", //随意定义
    "SecretKey": "dnX51glQ09THNpjFFntQiHqIk1HcuYxJ", //随意定义
    "Lifetime": 60 //单位分钟
  }
View Code

登录信息Passport:

using System.Collections.Generic;
using System.Security.Claims;
using System.Text.Json;

namespace Siia.MobileApi.Extensions
{
    public class Passport : IPassport
    {
        public bool IsAuthenticated { get; set; }

        /// <summary>
        /// 用户Id
        /// </summary>
        public int UserId { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 拥有的角色Id
        /// </summary>
        public List<int> RoleIds { get; set; }

        /// <summary>
        /// 手机号
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 组织Id
        /// </summary>
        public int OrganizationId { get; set; }

        public Passport(ClaimsPrincipal user)
        {
            if (user != null && user.Identity.IsAuthenticated)
            {
                this.IsAuthenticated = true;
                this.UserId = this.GetValue(user, "userId", -1);
                this.UserName = user.FindFirst("userName")?.Value;
                this.PhoneNumber = user.FindFirst("phoneNumber")?.Value;
                this.RoleIds = this.GetValue(user, "roleIds");
                this.OrganizationId= this.GetValue(user, "organizationId", -1);
            }
            else
            {
                this.IsAuthenticated = false;
                this.UserId = -1;
            }
        }

        private int GetValue(ClaimsPrincipal user, string type, int defaultValue)
        {
            if (user.FindFirst(type) == null) return defaultValue;
            return int.Parse(user.FindFirst(type).Value);
        }
        private List<int> GetValue(ClaimsPrincipal user, string type)
        {
            if (user.FindFirst(type) == null) return null;
            return JsonSerializer.Deserialize<List<int>>(user.FindFirst(type).Value);
        }
    }
}
View Code

IPassport:

public interface IPassport
    {
        bool IsAuthenticated { get; }
        /// <summary>
        /// 用户Id
        /// </summary>
        int UserId { get; }
        /// <summary>
        /// 用户名
        /// </summary>
        string UserName { get; }
        /// <summary>
        /// 拥有的角色Id
        /// </summary>
        List<int> RoleIds { get; }
        /// <summary>
        /// 手机号
        /// </summary>
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 组织Id
        /// </summary>
        public int OrganizationId { get; set; }
    }
View Code

获取授权token :

/// <summary>
        /// 账号密码用户登录接口 获取授权token
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("[action]")]
        public async Task<IActionResult> UserLogin([FromBody] AccountsLogin request)
        {
            //这里应该是需要去连接数据库做数据校验
            var _result = await _accountsService.UserLogin(request.UserName, request.Password);

            if (_result == null || !(_result.Status ?? false))
            {
                return Ok(ActionResponse.Fail(-1, _result.Message ?? "账号密码不正确"));
            }
            var clims = new Dictionary<string, string>();
            clims.Add("userId", _result.Data.Id.ToString());
            clims.Add("userName", _result.Data.UserName);
            clims.Add("organizationId", _result.Data.OrganizationId.ToString());
            clims.Add("roleIds", JsonConvert.SerializeObject(_result.Data.RoleIdList));
            var token = this._jwt.GetToken(clims);
            return Ok(ActionResponse.Succeed(new { token.token, token.expires, roleIds = _result.Data.RoleIdList }));
        }
View Code
原文地址:https://www.cnblogs.com/SmilePastaLi/p/15702931.html