任务15:oauth2 + oidc 实现 server部分
基于之前快速入门的项目(MvcCookieAuthSample):
ASP.NET Core快速入门(第5章:认证与授权)--学习笔记
ASP.NET Core快速入门(第6章:ASP.NET Core MVC)--学习笔记
mvcCookieAuthSample2下载地址:
http://video.jessetalk.cn/course/5/material/217/download
把这个 MVC 注册登录的网站变成一个单点登录,现在它是自己登录自己使用,我们需要把它的登录信息返回给第三方
添加 identityserver4 引用
在 startup 中
using IdentityServer4;
按照之前的文章添加 Config.cs
using System.Collections;
using System.Collections.Generic;
using IdentityServer4.Models;
using IdentityServer4.Test;namespace mvcCookieAuthSample
{public class Config{public static IEnumerable<Client> GetClients(){return new List<Client>{new Client(){ClientId = "client",AllowedGrantTypes = GrantTypes.Implicit,// 隐式模式ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = {"api"},}};}public static IEnumerable<ApiResource> GetApiResource(){return new List<ApiResource>{new ApiResource("api", "My Api")};}public static IEnumerable<IdentityResource> GetIdentityResources(){return new List<IdentityResource>{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Email(),};}public static List<TestUser> GetTestUsers(){return new List<TestUser>{new TestUser{SubjectId = "1",Username = "mingsonzheng",Password = "123456"}};}}
}
startup 的 ConfigureServices
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{services.AddIdentityServer().AddDeveloperSigningCredential().AddInMemoryClients(Config.GetClients()).AddInMemoryApiResources(Config.GetApiResource()).AddInMemoryIdentityResources(Config.GetIdentityResources()).AddTestUsers(Config.GetTestUsers());//services.AddDbContext<ApplicationDbContext>(options =>//{// options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));//});//services.AddIdentity<ApplicationUser, ApplicationUserRole>()// .AddEntityFrameworkStores<ApplicationDbContext>()// .AddDefaultTokenProviders();//services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)// .AddCookie(options => {// options.LoginPath = "/Account/Login";// });//services.Configure<IdentityOptions>(options =>//{// options.Password.RequireLowercase = true;// options.Password.RequireNonAlphanumeric = true;// options.Password.RequireUppercase = true;// options.Password.RequiredLength = 12;//});services.AddMvc();
}
startup 的 Configure 中 UseIdentityServer
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();//app.UseAuthentication();app.UseIdentityServer();app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});
}
我们已经把 IdentityServer4 添加到 MVC 程序中,接着需要在 Controller 中实现这个逻辑
首先注释 AccountController 原先的登录逻辑
//private UserManager<ApplicationUser> _userManager;
//private SignInManager<ApplicationUser> _signInManager;
Logout 中使用 HttpContext.SignOutAsync 替换
public async Task<IActionResult> Logout()
{//await _signInManager.SignOutAsync();await HttpContext.SignOutAsync();return RedirectToAction("Index", "Home");
}
接着改造登录的逻辑,我们需要验证用户名和密码,前面我们在 Config 中添加了 TestUser,它被放在 TestUserStore 中,可以通过依赖注入引用进来,有了它之后就可以在登录的时候拿到用户名和密码
private readonly TestUserStore _users;public AccountController(TestUserStore users)
{_users = users;
}
因为 TestUser 本身不提供 Email 登录,所以我们需要修改 LoginViewModel 以及 Login.cshtml
LoginViewModel
[Required]
//[DataType(DataType.EmailAddress)]
//public string Email { get; set; }
public string UserName { get; set; }
Login.cshtml
<div class="form-group"><label asp-for="UserName"></label><input asp-for="UserName" class="form-control" /><span asp-validation-for="UserName" class="text-danger"></span>
</div>
改造登录的逻辑
public async Task<IActionResult> Login(LoginViewModel loginViewModel,string returnUrl)
{if (ModelState.IsValid){//ViewData["ReturnUrl"] = returnUrl;//var user = await _userManager.FindByEmailAsync(loginViewModel.Email);//if (user == null)//{// ModelState.AddModelError(nameof(loginViewModel.Email), "Email not exists");//}//else//{// await _signInManager.SignInAsync(user, new AuthenticationProperties { IsPersistent = true });// return RedirectToLoacl(returnUrl);//}ViewData["ReturnUrl"] = returnUrl;var user = _users.FindByUsername(loginViewModel.UserName);if (user == null){ModelState.AddModelError(nameof(loginViewModel.UserName), "UserName not exists");}else{if (_users.ValidateCredentials(loginViewModel.UserName, loginViewModel.Password)){var props = new AuthenticationProperties{IsPersistent = true,ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30)),};await Microsoft.AspNetCore.Http.AuthenticationManagerExtensions.SignInAsync(HttpContext,user.SubjectId,user.Username,props);return RedirectToLoacl(returnUrl);}ModelState.AddModelError(nameof(loginViewModel.Password), "Wrong Password");}}return View();
}
这样,我们就实现了一个通过 IdentityServer4 下的方法来实现了一个登录逻辑,然后做了一个跳转,下一节再把客户端加进来
课程链接
http://video.jessetalk.cn/course/explore
相关文章
ASP.NET Core分布式项目实战(oauth2与open id connect 对比)--学习笔记
ASP.NET Core分布式项目实战(详解oauth2授权码流程)--学习笔记
ASP.NET Core分布式项目实战(oauth密码模式identity server4实现)--学习笔记
ASP.NET Core分布式项目实战(第三方ClientCredential模式调用)--学习笔记
ASP.NET Core分布式项目实战(客户端集成IdentityServer)--学习笔记
ASP.NET Core分布式项目实战(业务介绍,架构设计,oAuth2,IdentityServer4)--学习笔记
ASP.NET Core分布式项目实战(课程介绍,MVP,瀑布与敏捷)--学习笔记
ASP.NET Core快速入门 -- 学习笔记汇总