<五>oauth密码登录模式,identity server4服务端实现
1、首先先建立一个空的mvc项目实现一个简单的登录功能,我在网上找了个简单的登录代码:代码来源:Asp.Net Core 实现登录验证身份的功能
新增一个Login控制器和一个Login的前端页面,下面是代码,前端代码
@{ ViewData["Title"] = "登录"; } <h2 style="text-align:center">登录管理系统</h2> <hr /> <div> <form asp-controller="Home" asp-action="Login" method="post"> <div> <label class="control-label">用户名</label> <input class="form-control" type="text" name="username" /> </div> <div> <label class="control-label">密码</label> <input class="form-control" type="password" name="password" /> </div> <div class="form-group"> <input type="submit" value="登录" class="btn btn-primary" /> </div> </form> </div>
后端代码:
public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { return View(); } public IActionResult Login() { return View(); } /// <summary> /// post 登录请求 /// </summary> /// <returns></returns> [HttpPost] public async Task<IActionResult> Login(string userName, string password) { if (userName.Equals("admin") && password.Equals("123456")) { return Redirect("/Home/Index"); } return Json(new { result = false, msg = "用户名密码错误!" }); } /// <summary> /// 退出登录 /// </summary> /// <returns></returns> public async Task<IActionResult> Logout() { // await HttpContext.SignOutAsync(); return Redirect("/Login"); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
2、在mvc项目中配置Identityserver4服务(步骤跟第一篇大致一致,这里不再赘述)
namespace CodeAuthMvc { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryApiScopes(Config.GetScopes()) .AddInMemoryClients(Config.GetClients()) .AddTestUsers(Config.GetUsers().ToList()) .AddInMemoryIdentityResources(Config.GetIdentityResources()); services.AddControllersWithViews(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseIdentityServer(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Login}/{id?}"); }); } } }
public static class Config { public static IEnumerable<ApiScope> GetScopes() { return new ApiScope[] { new ApiScope("api1scope"), new ApiScope("api2scope"), //new ApiScope("scope2"), }; } // 这个 Authorization Server 保护了哪些 API (资源) public static IEnumerable<ApiResource> GetApiResources() { return new[] { new ApiResource("api", "My API") { Scopes = { "api1scope", "api2scope" } } }; } public static IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), }; } // 哪些客户端 Client(应用) 可以使用这个 Authorization Server public static IEnumerable<Client> GetClients() { return new[] { new Client { ClientId = "myself",//定义客户端 Id ClientSecrets = new [] { new Secret("secret".Sha256()) },//Client用来获取token AllowedGrantTypes = GrantTypes.Implicit,//隐式流程 AllowedScopes = new [] { "api1scope" }// 允许访问的 API 资源 } }; } //测试用户 public static IEnumerable<TestUser> GetUsers() { return new[] { new TestUser { SubjectId = "1", Username = "myname", Password = "password" } }; } }
3、利用identityserver官方给我们封装好的认证逻辑,修改controller中登录的逻辑
public class HomeController : Controller { private readonly ILogger<HomeController> _logger; private readonly TestUserStore _testUserStore; //identityserver封装的登录验证逻辑类 public HomeController(ILogger<HomeController> logger , TestUserStore testUserStore) { _testUserStore = testUserStore; _logger = logger; } public IActionResult Index() { return View(); } public IActionResult Login() { return View(); } /// <summary> /// post 登录请求 /// </summary> /// <returns></returns> [HttpPost] public async Task<IActionResult> Login(string userName, string password) { if(string.IsNullOrEmpty(userName.Trim())|| string.IsNullOrEmpty(password.Trim())) { return Json(new { result = false, msg = "用户名或者密码不能为空!" }); } var user = _testUserStore.FindByUsername(userName); if(user==null) { return Json(new { result = false, msg = "用户不存在!" }); } if( _testUserStore.ValidateCredentials(userName, password)) { return Redirect("/Home/Index"); } return Json(new { result = false, msg = "用户名密码错误!" }); } /// <summary> /// 退出登录 /// </summary> /// <returns></returns> public async Task<IActionResult> Logout() { // await HttpContext.SignOutAsync(); return Redirect("/Login"); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
4、运行mvc 测试一下是否成功,在登录页面输入在config中配置的user的名字和密码
点击登录,成功跳转到index