博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记录一次 .net core 2.0 JWT过程
阅读量:5932 次
发布时间:2019-06-19

本文共 15479 字,大约阅读时间需要 51 分钟。

本文章参考了其他朋友的博客,但是我确实不知道参考的谁了,所以自己记录一下,防止忘记。

首先创建了一个ApiAuthorizedByJWT类库·,具体内容如下(四部分分别是 生成的jwt类,角色权限对应关系,jwt验证方法,许可要求类):

1 using Microsoft.AspNetCore.Mvc; 2 using System; 3 using System.IdentityModel.Tokens.Jwt; 4 using System.Security.Claims; 5  6 namespace ApiAuthorizedByJWT 7 { 8     public class JWTAuthorizeCLASS 9     {10         public bool Status;11         public string access_token;12         public double expires_in;13         public string token_type;14         public static dynamic BuildOwnToken(Claim[] claims, PermissionRequirement permissionRequirement)15         {16             var now = DateTime.UtcNow;17             var jwt = new JwtSecurityToken(18                 issuer: permissionRequirement.Issuer,19                 audience: permissionRequirement.Audience,20                 claims: claims,21                 notBefore: now,22                 expires: now.Add(permissionRequirement.Expiration),23                 signingCredentials: permissionRequirement.SigningCredentials24             );25             var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);26             JWTAuthorizeCLASS rtres = new JWTAuthorizeCLASS27             {28                 Status = true,29                 access_token = encodedJwt,30                 expires_in = permissionRequirement.Expiration.TotalMilliseconds,31                 token_type = "Bearer"32             };33 34             35             return rtres;36         }37     }38 }

 

using System;using System.Collections.Generic;using System.Text;namespace ApiAuthorizedByJWT{    ///     /// 角色与权限url对应的类    ///     public class Permission    {        ///         /// 角色名称        ///         public virtual string RoleName { get; set; }        ///         /// 链接地址        ///         public virtual string Url { get; set; }    }    }
using Microsoft.AspNetCore.Authentication;using Microsoft.AspNetCore.Authorization;using Microsoft.Extensions.DependencyInjection;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;/// /// 这里必须注意:此处引用了nuget包:Microsoft.AspNetCore.Mvc.Abstractions;否则这个Microsoft.AspNetCore.Mvc不存在 以及Microsoft.AspNetCore.All/// namespace ApiAuthorizedByJWT{    public class PermissionHandler : AuthorizationHandler
{ ///
/// 验证方案提供对象 /// public IAuthenticationSchemeProvider Schemes { get; set; } ///
/// 自定义策略参数 /// public PermissionRequirement Requirement { get; set; } ///
/// 构造 /// ///
public PermissionHandler(IAuthenticationSchemeProvider schemes) { Schemes = schemes; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { ////赋值用户权限 Requirement = requirement; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext; //请求Url var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService
(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler; if (handler != null && await handler.HandleRequestAsync()) { context.Fail(); return; } } //判断请求是否拥有凭据,即有没有登录 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name); //result?.Principal不为空即登录成功 if (result?.Principal != null) { httpContext.User = result.Principal; //权限中是否存在请求的url if (Requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0) { var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == requirement.ClaimType).Value; //验证权限 if (Requirement.Permissions.Where(w => w.RoleName == name && w.Url.ToLower() == questUrl).Count() <= 0) { context.Fail(); return; } context.Succeed(requirement); } return; //var userroles = requirement.Permissions; } } if (!questUrl.Equals(Requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType)) { context.Fail(); return; } context.Succeed(requirement); } }}
using Microsoft.AspNetCore.Authorization;using Microsoft.IdentityModel.Tokens;using System;using System.Collections.Generic;using System.Text;namespace ApiAuthorizedByJWT{    ///     /// 许可要求    ///     public class PermissionRequirement:IAuthorizationRequirement    {        ///         /// 用户权限集合        ///         public List
Permissions { get; private set; } ///
/// 无权限action /// public string DeniedAction { get; set; } = "/Api/ReLogin"; ///
/// 认证授权类型 /// public string ClaimType { internal get; set; } ///
/// 请求路径 /// public string LoginPath { get; set; } = "/Api/Login"; ///
/// 发行人 /// public string Issuer { get; set; } ///
/// 订阅人 /// public string Audience { get; set; } ///
/// 过期时间 /// public TimeSpan Expiration { get; set; } = TimeSpan.FromMinutes(60); ///
/// 签名验证 /// public SigningCredentials SigningCredentials { get; set; } ///
/// 构造 /// ///
拒约请求的url ///
权限集合 ///
声明类型 ///
发行人 ///
订阅人 ///
签名验证实体 public PermissionRequirement(string deniedAction, List
permissions, string claimType, string issuer, string audience, SigningCredentials signingCredentials) { ClaimType = claimType; DeniedAction = deniedAction; Permissions = permissions; Issuer = issuer; Audience = audience; SigningCredentials = signingCredentials; } }}

那么在真正的使用中,要在core中添加上对应的一些数据信息。首先常见一个关于登录用户的类

using ApiAuthorizedByJWT;using Dapper;using Microsoft.Extensions.Options;using Microsoft.IdentityModel.Tokens;using new_m1_1_0.Models.interfaces;using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Security.Claims;using System.Text;using System.Threading.Tasks;namespace new_m1_1_0.Models.models{    public class LoginUser:ILoginUser    {        public string Username;        public string UserID;        public string Accid;        public string Password;        public string Acctoken;        public List
LRC; public JWTAuthorizeCLASS apitoken; private bool isInit = false; public LoginUser(string ID,string Key,Func
CheckMethed, string connectstring) { //--------------------校验方法-------------------------------- //pass if (CheckMethed(ID, Key, connectstring)) { Password = Key; IDbConnection conn = new MySql.Data.MySqlClient.MySqlConnection(connectstring); string sql1 = "select a.user_name,a.role_key,b.name,b.remark,c.url,c.name as func_name,c.sourse,d.resource_key,e.source_name from m1_user_roles a,m1_role b,m1_resource c,m1_permission d,m1_sourse e where a.user_name = @ID and b.role_key = a.role_key and d.role_key = a.role_key and c.resource_key = d.resource_key and e.source_key = c.sourse and e.role_key = a.role_key"; List
loginUserInfo = conn.Query
(sql1, new { id = ID }).ToList(); string sql2 = "select a.user_name,a.accid,a.acctoken,b.nick_name from m1_user_im a,m1_user b where a.user_name = @id and b.user_name = a.user_name"; List < LoginUserNeteaseInfo> loginUserNeteaseInfo = conn.Query
(sql2, new { id = ID }).ToList(); LRC = new List
(); List
sourseL = new List
(); for (int i = 0; i < loginUserInfo.Count; i++) { if (!sourseL.Contains(loginUserInfo[i].sourse)) { sourseL.Add(loginUserInfo[i].sourse); SourceWithRole sourceWithRole = new SourceWithRole(); sourceWithRole.L = new List
(); var rwc = new RoleWithCode(); rwc.Code = loginUserInfo[i].resource_key; rwc.RoleName = loginUserInfo[i].name; rwc.RoleKey = loginUserInfo[i].role_key; rwc.Url = loginUserInfo[i].url; sourceWithRole.L.Add(rwc); sourceWithRole.SourceCode = loginUserInfo[i].sourse; sourceWithRole.SourceName = loginUserInfo[i].source_name; LRC.Add(sourceWithRole); } else { for (int j = 0; j < LRC.Count; j++) { if (LRC[j].SourceCode == loginUserInfo[i].sourse) { var rwc = new RoleWithCode(); rwc.Code = loginUserInfo[i].resource_key; rwc.RoleName = loginUserInfo[i].name; rwc.RoleKey = loginUserInfo[i].role_key; rwc.Url = loginUserInfo[i].url; LRC[j].L.Add(rwc); } else { continue; } } } } try { Username = loginUserNeteaseInfo[0].nick_name; Accid = loginUserNeteaseInfo[0].accid; Acctoken = loginUserNeteaseInfo[0].acctoken; UserID = loginUserNeteaseInfo[0].user_name; this.apitoken = GetLoginUserToken(); } catch (Exception ex) { Username = ""; Accid = ""; Acctoken = ""; UserID = ""; LRC = null; } } else { Username = ""; UserID = ""; Password = ""; Accid = ""; Acctoken = ""; LRC = null; } } public JWTAuthorizeCLASS GetLoginUserToken() { if (LRC == null || LRC.Count < 1) { return null; } var symmetricKeyAsBase64 = "TTT11111TTT111TTTTT11TTTTTT11111111111";//audienceConfig["Secret"]; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); var signingKey = new SymmetricSecurityKey(keyByteArray); var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); int apicount = 0; List
roles = new List
(); var permission = new List
(); for (int i = 0; i < LRC.Count; i++) { for (int j = 0; j < LRC[i].L.Count; j++) { if (roles.Contains(LRC[i].L[j].RoleKey)) { } else { roles.Add(LRC[i].L[j].RoleKey); } permission.Add(new Permission { Url = LRC[i].L[j].Url,RoleName= LRC[i].L[j].RoleKey}); } } List
claimArray = new List
(); for (int i = 0; i < roles.Count; i++) { claimArray.Add(new Claim(ClaimTypes.Role, roles[i])); } claimArray.Add(new Claim(ClaimTypes.Name, UserID)); return JWTAuthorizeCLASS.BuildOwnToken(claimArray.ToArray(), new PermissionRequirement("/api/login", permission, ClaimTypes.Role, "lsnct", "everyone", signingCredentials)); } } public class RoleWithCode { ///
/// 角色名称 /// public string RoleName; ///
/// 权限code /// public string Code; ///
/// 链接 /// public string Url; ///
/// 角色关键字 /// public string RoleKey; } public class SourceWithRole { ///
/// 资源模块代码 /// public string SourceCode; ///
/// 资源模块名称 /// public string SourceName; ///
/// 所属角色与api列表 /// public List
L; }}

 

然后在控制器中处理

[HttpPost]        public JsonResult Post()        {                        var username = HttpContext.Request.Form["username"].ToString().Trim();//获取            var pwd = HttpContext.Request.Form["pwd"].ToString().Trim();            LoginUser LU = new LoginUser(username,pwd,CheckLogin.checkmethed1, appSettings.dbcc_sys);            LU.Password = "";            return new JsonResult(LU);                   }

生成了token后,后面会拿这个token访问接口。

在对应的工程的startup.cs中处理

var symmetricKeyAsBase64 = "TTT11111TTT111TTTTT11TTTTTT11111111111";//audienceConfig["Secret"]; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);            var signingKey = new SymmetricSecurityKey(keyByteArray);            var tokenValidationParameters = new TokenValidationParameters            {                ValidateIssuerSigningKey = true,                IssuerSigningKey = signingKey,                ValidateIssuer = true,                ValidIssuer = "lsnct", //audienceConfig["Issuer"],                ValidateAudience = true,                ValidAudience = "everyone",                //audienceConfig["Audience"],                ValidateLifetime = true,                ClockSkew = TimeSpan.Zero            };            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);            services.AddAuthorization(options =>            {                //var permission = GetAllPermission();                List
permission = null; if (permission == null) { //这个集合模拟用户权限表,可从数据库中查询出来 permission = new List
{
new Permission { Url="/api/getValues1", RoleName="system"}, new Permission { Url="/api/values/getValues1", RoleName="admin"}, new Permission{ Url="/api/getValues3", RoleName="admin"}, new Permission{ Url="/api/Products/GetMomentDetails", RoleName="system"} }; } //如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名 //var permissionRequirement = new PermissionRequirement("/api/denied", permission, ClaimTypes.Role, audienceConfig["Issuer"], audienceConfig["Audience"], signingCredentials); var permissionRequirement = new PermissionRequirement("/Api/Login", permission, ClaimTypes.Role, "lsnct", "everyone", signingCredentials); options.AddPolicy("Permission", policy => policy.Requirements.Add(permissionRequirement)); }).AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o => { //不使用https o.RequireHttpsMetadata = false; o.TokenValidationParameters = tokenValidationParameters; }); //注入授权Handler services.AddSingleton
(); services.AddMvc() .AddJsonOptions(options=> { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;//忽略循环引用 options.SerializerSettings.ContractResolver = new DefaultContractResolver();//不使用驼峰样式key options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";//时间格式化 });

 

最后在对应接口加上[Authorize("Permission")]标记即可。

 

转载于:https://www.cnblogs.com/lsnct/p/8474229.html

你可能感兴趣的文章
django多对多数据库建立 以及数据的传输 并进行增加 删除 修改
查看>>
类似于京东商城等的商品分类搜索筛选功能实现
查看>>
032最长有效括号
查看>>
【数据结构 JavaScript版】- web前端开发精品课程【红点工场】--javascript--栈的概念...
查看>>
js动态改变根元素字体大小
查看>>
Python系列:三、流程控制循环语句--技术流ken
查看>>
博客的"Hello World"
查看>>
python logger日志配置
查看>>
django中使用AJAX时如何获取表单参数(按钮携带参数)
查看>>
List洗牌和权重选取算法
查看>>
leetcode_20.c++有效的括号
查看>>
C# 之泛型详解
查看>>
iOS扩展Extension之Today
查看>>
MyBatis参数绑定规则及原理分析
查看>>
vue中表单的动态绑定
查看>>
YAML 在Python中的应用
查看>>
Jmeter(参数化)
查看>>
[JSOI2008]最大数maxnumber
查看>>
Python基础知识之json&pickle模块
查看>>
maven安装及配置
查看>>