<六>OIDC 客戶端的引用服務端登入頁面的實現
阿新 • • 發佈:2020-10-26
上一節服務端已經弄好了,那麼我們來建立一個mvc客戶端,訪問客戶端的時候直接呼叫服務端的登入頁面實現登入。
1、建立一個mvcclient, 埠預設為5004。
startup類中的 ConfigureServices函式總中加入認證配置
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.SignInScheme = "Cookies"; options.Authority = "http://localhost:5003";//identity伺服器域名 options.RequireHttpsMetadata= false; //沒有證書啥的不需要傳 options.ClientId = "myself"; //MVC服務端配置的clientId options.ClientSecret = "secret"; options.SaveTokens = true; }); services.AddControllersWithViews(); }
config中加入
app.UseAuthentication(); app.UseAuthorization();
預設的Homecontroller上面加上認證特性[Authorize]
這樣客戶端的配置就可以了。
2、修改一下服務端的程式碼
2.1、修改login前端,新增接收回調連結的引數
@{ ViewData["Title"] = "登入"; } <h2 style="text-align:center">登入管理系統</h2> <hr /> <div> <form asp-controller="Account" 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> <input type="text" class="form-control" id="returnUrl" name="returnUrl" value="@ViewData["Rurl"]" /> </form> </div>
2.2、修改controller中的登入邏輯
public class AccountController : Controller { private readonly TestUserStore _testUserStore; public AccountController( TestUserStore testUserStore) { _testUserStore = testUserStore; } public IActionResult Index() { return View(); } public IActionResult Login(string returnUrl = "/Home/Index") { ViewData["Rurl"] = returnUrl; return View(); } /// <summary> /// post 登入請求 /// </summary> /// <returns></returns> [HttpPost] public async Task<IActionResult> Login(string userName, string password,string returnUrl) { if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password)) { 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)) { var props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(3)) }; await AuthenticationManagerExtensions.SignInAsync( HttpContext, new IdentityServerUser(user.SubjectId), props ); return Redirect(returnUrl); } return Json(new { result = false, msg = "使用者名稱密碼錯誤!" }); } }
2.3、修改identity 中的配置 config.cs
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,//隱式流程 RequireConsent=false, RedirectUris={"http://localhost:5004/signin-oidc"},//這個在identity的地址中是固定的,登入成功回撥處理地址,處理回撥返回的資料 PostLogoutRedirectUris = { "http://localhost:5004/signout-callback-oidc" },//退出的時候會返回到這個地址 AllowedScopes = { IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OpenId, }// 允許訪問的 API 資源 } }; } //測試使用者 public static IEnumerable<TestUser> GetUsers() { return new[] { new TestUser { SubjectId = "1", Username = "myname", Password = "password" } }; } }
2.4、在服務端startup中引用配置
public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer().AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryApiScopes(Config.GetScopes()) .AddInMemoryClients(Config.GetClients()) .AddTestUsers(Config.GetUsers().ToList()) .AddInMemoryIdentityResources(Config.GetIdentityResources()); services.AddControllersWithViews(); }
AddDeveloperSigningCredential()這個是開發的簽名憑據,只能在開發使用,部署時需要更換。。這裡一定要加上,不然會報Nosigningcredentialisconfigured 的錯誤。
3、執行服務端和客戶端,瀏覽器訪問localhost:5004 就會跳到登入頁面,如下圖所示,這裡我把returnurl給顯示出來了。
4、輸入使用者名稱和密碼,即使服務端config.cs裡面TestUser配置的使用者名稱和密碼登入後就自動跳轉到client 埠5004的主頁面
如果客戶端沒有加上 app.UseAuthentication(); 的話會報signin-oidc 的頁面404的情況,也就說明了UseAuthentication會自動去解析cookie中的認證資料