日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

实现一个登录:Mac+.NET 5+Identity+JWT+VS Code

發布時間:2023/12/4 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现一个登录:Mac+.NET 5+Identity+JWT+VS Code 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

.NET圈兒的朋友們,大家好!我可太喜歡如今開源的.Net了,寫代碼很巴適!所以今天分享一下之前學習的一個登錄小案例,代碼有不足之處歡迎指正!!!

工具:采用VS Code及其插件開發,輕量化的同時減少命令行的敲寫,使用VS沒有沖突哈

一、通過插件創建WebApi項目

原文是個動圖,可點擊原文查看

二、利用插件下載項目所需要的Nuget包

三、代碼編寫

①新建User實體

///?<summary> ///?登錄用戶實體類??繼承Identiy框架提供的?IdentityUser類 ///?</summary> public?class?AppUser:IdentityUser {//?自己再擴充三個字段public?DateTime?DateCreated?{?get;?set;?}public?DateTime?DateModified?{?get;?set;?}public?string?FullName?{?get;?set;?}? }

②新建一個上下文類

public?class?AppDBContext?:?IdentityDbContext<AppUser,?IdentityRole,?string> {public?AppDBContext(DbContextOptions?options)?:?base(options){} }

③在Startup依賴注入上下文類

services.AddDbContext<AppDBContext>(options?=> {options.UseMySql(Configuration.GetConnectionString("DefaultConnection"),?MySqlServerVersion.LatestSupportedServerVersion); }); //?AddEntityFrameworkStores?用來創建?用戶和密碼之間的服務 services.AddIdentity<AppUser,?IdentityRole>(opt?=>?{?}).AddEntityFrameworkStores<AppDBContext>();

④在終端codefirst生成數據表

dotnet?ef?migrations?add?init dotnet?ef??database?update

⑤配置JWT

ConfigureServices方法里面配置服務

services.AddAuthentication(x?=> {x.DefaultAuthenticateScheme?=?JwtBearerDefaults.AuthenticationScheme;x.DefaultChallengeScheme?=?JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options?=>{//?jwt的?key?需要設置復雜點?var?key?=?Encoding.ASCII.GetBytes(Configuration["JWTConfig:Key"]);var?issure?=?Configuration["JWTConfig:Issuer"];???//?發行人?var?audience?=?Configuration["JWTConfig:Audience"];??//?受眾???options.TokenValidationParameters?=?new?TokenValidationParameters(){ValidateIssuerSigningKey?=?true,IssuerSigningKey?=?new?SymmetricSecurityKey(key),ValidateIssuer?=?true,?//?設置為True時?ValidIssure?屬性設置下?不然jwt驗證不會通過ValidateAudience?=?true,?//?同上?ValidAudience?屬性設置下??RequireExpirationTime?=?true,?ValidateLifetime=true,???//??token失效緩沖時間?默認是五分鐘?失效時間需要加上這五分鐘緩沖//??如果?上面?ValidateIssuer??配置為false?則不需要下面兩個屬性ValidIssuer?=?issure,ValidAudience?=?audience,};}); //?多角色時?可以這樣配置??[Authorize(Policy?="PolicyGroup")]?動作方法上可以簡寫 services.AddAuthorization(options?=> {options.AddPolicy("PolicyGroup",?policy?=>?policy.RequireRole("Admin",?"User")); });

Configure 方法里面使用服務

public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env) {if?(env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseSwagger();app.UseSwaggerUI(c?=>?c.SwaggerEndpoint("/swagger/v1/swagger.json",?"SwaggerDemo?v1"));}app.UseHttpsRedirection();app.UseCors("any");app.UseRouting();//?注意順序app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints?=>{endpoints.MapControllers();}); }

⑥swagger配置

ConfigureServices方法里面配置服務

services.AddSwaggerGen(c?=> {c.SwaggerDoc("v1",?new?OpenApiInfo?{?Title?=?"SwaggerDemo",?Version?=?"v1",?Description?=?"Demo?API?for?showing?Swagger"?});//?下面兩步配置?實現?swagger?上面?“鎖”c.AddSecurityDefinition("Bearer",?new?OpenApiSecurityScheme{In?=?ParameterLocation.Header,??//?位于HeaderDescription?=?"請于此處直接填寫token?無需?Bearer然后再加空格的形式",Name?=?"Authorization",Type?=?SecuritySchemeType.Http,BearerFormat?=?"JWT",Scheme?=?"bearer"});c.AddSecurityRequirement(new?OpenApiSecurityRequirement{{new?OpenApiSecurityScheme{Reference=new?OpenApiReference{Type=ReferenceType.SecurityScheme,Id="Bearer"}},Array.Empty<string>()}});//?swagger接口注釋顯示?//?注意?vscode?用戶需要在項目的csproj文件里面手動配置生成注釋文檔的屬性??//?具體參見項目文件里的PropertyGroupvar?fileName?=?$"{Assembly.GetExecutingAssembly().GetName().Name}.xml";var?filePath?=?Path.Combine(AppContext.BaseDirectory,?fileName);c.IncludeXmlComments(filePath); });

Configure 方法里面使用服務

public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env) {if?(env.IsDevelopment()){app.UseDeveloperExceptionPage();//?swagger?中間件使用app.UseSwagger();//?此處的?v1?必須與上面c.SwaggerDoc("v1")?里的一致app.UseSwaggerUI(c?=>?c.SwaggerEndpoint("/swagger/v1/swagger.json",?"SwaggerDemo?v1"));}app.UseHttpsRedirection();app.UseCors("any");app.UseRouting();//?注意順序app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints?=>{endpoints.MapControllers();}); }

⑦創建UserController,并通過構造函數注入登錄服務

private?readonly?UserManager<AppUser>?_userManger;??//?用戶服務 private?readonly?SignInManager<AppUser>?_signInManger;??//?登錄服務private?readonly?RoleManager<IdentityRole>?_roleManger;?//?角色服務 private?readonly?JWTConfig?_jwtConfig;??//?配置框架將配置文件注入實體類 public?UserController(ILogger<UserController>?logger,?UserManager<AppUser>?userManager,SignInManager<AppUser>?signInManager,?IOptions<JWTConfig>?jwtConfig,?RoleManager<IdentityRole>?roleManger) {this._logger?=?logger;this._userManger?=?userManager;this._signInManger?=?signInManager;this._jwtConfig?=?jwtConfig.Value;this._roleManger?=?roleManger; }

注冊用戶

///?<summary> ///?用戶注冊 ///?AddAndUpdateUserrRegisterModel?是一個Dto?接受對象 ///?AllowAnonymous?不需要權限驗證 ///?作者?xxxx ///?</summary> ///?<param?name="model"></param> ///?<returns></returns> [AllowAnonymous] [HttpPost("RegisterUser")] public?async?Task<Object>?RegisterUser(AddAndUpdateUserrRegisterModel?model) {try{//?check??注冊的時候是否包含角色if?(model.Roles?is?null?||?model.Roles.Count?<=?0){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"角色不能為空"));}//?循環判斷用戶所注冊的角色時候存在?創建角色的方法??AddRole()foreach?(var?item?in?model.Roles){if?(!await?_roleManger.RoleExistsAsync(item)){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"不存在創建的角色"));}}//?生成一個用戶類var?user?=?new?AppUser(){UserName?=?model.Email,FullName?=?model.FullName,Email?=?model.Email,DateCreated?=?DateTime.Now,DateModified?=?DateTime.UtcNow};//?注冊用戶?var?result?=?await?_userManger.CreateAsync(user,?model.Password);if?(result.Succeeded){//?注冊成功后?獲取臨時剛剛創建的用戶??var?tempUser?=?await?_userManger.FindByEmailAsync(model.Email);//?循環給創建的用戶添加角色foreach?(var?role?in?model.Roles){await?_userManger.AddToRoleAsync(tempUser,?role);?//?添加角色}return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Ok,?"用戶被成功注冊!",?null));}//?創建用戶失敗返回return?await?Task.FromResult(string.Join(",",?result.Errors.Select(x?=>?x.Description).ToArray()));}catch?(System.Exception?ex){//?異常返回return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?ex.Message,?null));} }

登錄

///?<summary> ///?生成Token ///?作者?xxxx ///?</summary> ///?<param?name="user"></param> ///?<returns></returns> private?string?GenarateToken(AppUser?user,?List<string>?roles) {var?jwtTokenHandle?=?new?JwtSecurityTokenHandler();var?key?=?Encoding.ASCII.GetBytes(_jwtConfig.Key);//?配置?Subjectvar?claims?=?new?List<Claim>(){new?Claim(JwtRegisteredClaimNames.NameId,user.Id),new?Claim(JwtRegisteredClaimNames.Email,user.Email),new?Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())};foreach?(var?role?in?roles){claims.Add(new?Claim(ClaimTypes.Role,role));}var?tokenDescriptor?=?new?SecurityTokenDescriptor{//?多重角色Subject=new?ClaimsIdentity(claims),?//?單一角色//?Subject?=?new?ClaimsIdentity(new[]//?{//?????new?System.Security.Claims.Claim(JwtRegisteredClaimNames.NameId,user.Id),//?????new?System.Security.Claims.Claim(JwtRegisteredClaimNames.Email,user.Email),//?????new?System.Security.Claims.Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())//?????//?new?System.Security.Claims.Claim(ClaimTypes.Role,"role")//?}),//?過期時間?12小時??Expires?=?DateTime.UtcNow.AddSeconds(6),SigningCredentials?=?new?SigningCredentials(new?SymmetricSecurityKey(key),?SecurityAlgorithms.HmacSha256Signature),Audience?=?_jwtConfig.Audience,??//?這里不配置?也會返回UnAuthorized?Issuer?=?_jwtConfig.Issuer?//?同上};//?創建tokenvar?token?=?jwtTokenHandle.CreateToken(tokenDescriptor);return?jwtTokenHandle.WriteToken(token); }///?<summary> ///?用戶登錄 ///?LoginModel?登錄Dto接收 ///?作者?xxxx ///?</summary> ///?<param?name="model"></param> ///?<returns></returns> [AllowAnonymous] [HttpPost] public?async?Task<object>?Login(LoginModel?model) {try{if?(!ModelState.IsValid){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"參數不合法!",?null));}var?result?=?await?_signInManger.PasswordSignInAsync(model.UserName,?model.Password,?false,?false);if?(result.Succeeded){//?成功的話獲取用戶var?appUser?=?await?_userManger.FindByNameAsync(model.UserName);var?roles?=?(await?_userManger.GetRolesAsync(appUser)).ToList();//?await?_userManger.GetRolesAsync(appUser);var?user?=?new?UserDto(appUser.FullName,?appUser.Email,?appUser.UserName,?appUser.DateCreated,?roles){//?生成Token?Token?=?GenarateToken(appUser,roles)};return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Ok,?"登錄成功",?user));}else{return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"登錄失敗",?null));}}catch?(System.Exception?ex){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?ex.Message,?null));} }

添加角色

先將上文用戶登錄產生的token 設置到swagger里面,然后訪問只有 Admin 角色可以訪問的接口

///?<summary> ///?添加角色 ///?[Authorize(Roles?="Admin")]??只有Admin角色的用戶可以訪問 ///?作者?xxx ///?</summary> ///?<param?name="model"></param> ///?<returns></returns> [Authorize(Roles?="Admin")] [HttpPost("AddRole")] public?async?Task<object>?AddRole(AddRoleModel?model) {try{if?(model?is?null?||?string.IsNullOrWhiteSpace(model.Role)){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"角色不能為空"));}//?判斷【AspNetRoles】?表里??角色是否存在??if?(await?_roleManger.RoleExistsAsync(model.Role)){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Ok,?"角色存在了"));}var?role?=?new?IdentityRole(){Name?=?model.Role,};//?創建角色var?result?=?await?_roleManger.CreateAsync(role);if?(result.Succeeded){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Ok,?"角色創建成功!"));}else{return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error,?"角色創建失敗!"));}}catch?(System.Exception){return?await?Task.FromResult(new?ResponseModel(Enums.ResponseCode.Error));}}

關于我們token權限在校驗時出現失敗怎么辦?這里Asp.Net Core 5.0 新增一個接口【IAuthorizationMiddlewareResultHandler】可以處理權限驗證 ?看下文代碼展示!

///?<summary> ///?這個是Asp.Net Core 5 新增的授權處理失敗??可以直接暴露出請求上下文?省事很多啦!!! ///?作者?xxx ///?</summary> public?class?AuthorizationHandleMiddleWare?:?IAuthorizationMiddlewareResultHandler {private?readonly?AuthorizationMiddlewareResultHandler?authorizationHandleMiddleWare?=new();public?async?Task?HandleAsync(RequestDelegate?next,?HttpContext?context,?AuthorizationPolicy?policy,?PolicyAuthorizationResult?authorizeResult){//?當?token失效或者token不存在的時候?authorizeResult.Challenged?為Trueif(authorizeResult.Challenged)?{//?todo?拿到上下文user對象后?此處可以check?token??區分token是否是過期了var?a=context.Request.Headers["Authorization"];context.Response.StatusCode=(int)HttpStatusCode.OK;await?context.Response.WriteAsJsonAsync(new?ResponseModel(Enums.ResponseCode.UnAuthorized,"您未授權,請檢查Token是否有效!"));return?;}//?此時token?校驗通過??但是訪問的資源的沒權限的話?authorizeResult.Forbidden?為trueif(authorizeResult.Forbidden){context.Response.StatusCode=(int)HttpStatusCode.OK;await?context.Response.WriteAsJsonAsync(new?ResponseModel(Enums.ResponseCode.ForBidden,"您無此權限訪問哦!"));return?;}await?authorizationHandleMiddleWare.HandleAsync(next,context,policy,authorizeResult);} }

另外還需要在ConfigureService里面注冊下服務

//?.net?5?新增的權限驗證中間件??在此處依賴注入一下??詳見?AuthorizationHandleMiddleWare.cs?文件 services.AddSingleton<IAuthorizationMiddlewareResultHandler,AuthorizationHandleMiddleWare>();

以上就是一個登錄的簡單demo,詳細代碼請訪問碼云

作者:Jarry

原文鏈接:https://blog.csdn.net/qbc12345678/article/details/120758144

文中源碼托管Gitee:https://gitee.com/holyace/together/tree/JarryGu_develop/framework/JwtLoginDemo

作者QQ技術交流群:346250023

總結

以上是生活随笔為你收集整理的实现一个登录:Mac+.NET 5+Identity+JWT+VS Code的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。