git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.gitjavascript
2.一、《IdentityServer4 (1) 客戶端受權模式(Client Credentials)》
2.二、《IdentityServer4 (2) 密碼受權(Resource Owner Password)》
2.三、《IdentityServer4 (3) 受權碼模式(Authorization Code)》
2.四、《IdentityServer4 (4) 靜默刷新(Implicit)》
2.五、《IdentityServer4 (5) 混合模式(Hybrid)》html
IdentityServer4 中文文檔 http://www.identityserver.com.cn/
IdentityServer4 英文文檔 https://identityserver4.readthedocs.io/en/latest/
OpenID Connect 官網 https://openid.net/connect/
OpenID Connect 中文 https://www.cnblogs.com/linianhui/p/openid-connect-core.html
OpenID Connect和OAuth 2.0對比:https://www.jianshu.com/p/d453076e6433
Oauth 2.0 官網:https://oauth.net/2/
Oauth 2.0 受權框架:https://tools.ietf.org/html/rfc6749#section-4.2.1java
一、客戶端準備一個包含所需請求參數的身份驗證請求。
二、客戶端將請求發送到受權服務器(填寫帳號密碼)。
三、受權服務器對最終用戶進行身份驗證(驗證帳號密碼和客戶端)。
四、受權服務器得到最終用戶贊成/受權。
五、受權服務器使用IdToken和AccessToken(若是要求)將最終用戶發送回客戶端。git
new Client{ ClientId="mvc client implicit", //客戶端Id ClientName="測試客戶端 Implicit", //客戶端名稱 隨便寫 //Implicit 模式 由於token 是經過瀏覽器發送給客戶端的,這裏必須啓用 AllowAccessTokensViaBrowser=true, AllowedGrantTypes=GrantTypes.Implicit,//驗證模式 RedirectUris = { "http://localhost:5003/callback.html", // AccessToken 有效期比較短,刷新 AccessToken 的頁面 "http://localhost:5003/silentref.html", }, //是否須要用戶點擊贊成,這裏須要設置爲 false,否則客戶端靜默刷新不可用 RequireConsent=false, AllowedCorsOrigins={ "http://localhost:5003" }, //註銷重定向的url PostLogoutRedirectUris = { "http://localhost:5003" }, AccessTokenLifetime=10, //客戶端訪問權限 AllowedScopes = { "api1", IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Email, IdentityServerConstants.StandardScopes.Address, IdentityServerConstants.StandardScopes.Phone, IdentityServerConstants.StandardScopes.Profile } },
git地址:https://github.com/IdentityModel/oidc-client-js github
我直接使用的/home/index 在裏面添加請求受權代碼ajax
<style> .box { height: 200px; overflow: auto; border: 1px solid #ccc } .btn-box { margin-top: 10px; } .btn-box button { margin-right: 10px; } </style> <div class="row btn-box"> <button class="btn btn-primary" onclick="login()">登錄 Implicit</button> <button class="btn btn-primary" onclick="getuser()">獲取 User Implicit</button> <button class="btn btn-primary" onclick="getapi()">測試 API Implicit</button> <button class="btn btn-primary" onclick="removeUser()">清除 User Implicit</button> <button class="btn btn-primary" onclick="iframeSignin()">刷新 User Implicit</button> </div> <hr /> <div class="row"> <h3>User:</h3> <div id="userinfo" class="col-md-12 box"> </div> </div> <div class="row"> <h3>API:</h3> <div id="apiresult" class="col-md-12 box"> </div> </div> @section Scripts{ <script src="~/lib/oidc/oidc-client.min.js"></script> <script type="text/javascript"> Oidc.Log.logger = window.console; Oidc.Log.level = Oidc.Log.DEBUG; var log = function (msg) { console.log(msg); } var testconfig = { authority: "http://localhost:5002", client_id: "mvc client implicit", redirect_uri: "http://localhost:5003/callback.html", response_type: "id_token token", scope: "api1 openid email phone address profile", clockSkew: 0, //啓用靜默刷新token silent_redirect_uri: "http://localhost:5003/silentref.html", automaticSilentRenew: true, }; var mgr = new Oidc.UserManager(testconfig); mgr.events.addUserLoaded(function (user) { console.log("user loaded", user); mgr.getUser().then(function () { console.log("getUser loaded user after userLoaded event fired"); }); }); mgr.events.addUserUnloaded(function () { console.log("user unloaded"); }); mgr.events.addAccessTokenExpiring(function () { log("Access token expiring..." + new Date()); }); mgr.events.addSilentRenewError(function (err) { log("Silent renew error: " + err.message); }); mgr.events.addUserSignedOut(function () { log("User signed out of OP"); mgr.removeUser(); }); var login = function () { mgr.signinRedirect(); }; var getuser = function () { mgr.getUser().then(function (user) { log("got user"); $('#userinfo').html(JSON.stringify(user)); }).catch(function (err) { log(err); }); }; var removeUser = function () { mgr.removeUser().then(function () { log("user removed"); }).catch(function (err) { log(err); }); } var iframeSignin = function () { mgr.signinSilent().then(function (user) { log("signed in", user); }).catch(function (err) { log(err); }); } var getapi = function (token) { mgr.getUser().then(function (user) { log("get user success"); document.getElementById('userinfo').innerHTML = JSON.stringify(user); var settings = { url: 'http://localhost:5001/api/suibian', beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + user.access_token) console.log("beforeSend", xhr) }, success: function (res) { console.log("api result success:", res); $('#apiresult').html(JSON.stringify(res)); }, error: function (res) { console.log("api result error:", res); $('#apiresult').html(res.responseText); } } $.ajax(settings); }).catch(function (err) { log(err); }); }; </script> }
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Oidc-Client</title> <script src="lib/oidc/oidc-client.min.js"></script> </head> <body> 登錄中... </body> </html> <script> new Oidc.UserManager().signinRedirectCallback().then(function (user) { //console.log("signin response success"); //console.log(user) //document.getElementById("message").innerText = JSON.stringify(user); location.href = "/home"; }).catch(function (err) { console.log(err); }); </script>
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Oidc-Client</title> </head> <body> <h1>Silent.html</h1> </body> </html> <script src="lib/oidc/oidc-client.min.js"></script> <script> new Oidc.UserManager().signinSilentCallback() .catch((err) => { console.log("refresh", err); }); </script>
ConfigureServices()json
services.AddCors(options => { options.AddPolicy("client1", policy => { //客戶端地址 policy.WithOrigins("http://localhost:5003"); policy.AllowAnyHeader(); policy.AllowAnyMethod(); }); }); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { // IdentityServer 地址 options.Authority = "http://localhost:5002"; //不須要https options.RequireHttpsMetadata = false; //這裏要和 IdentityServer 定義的 api1 保持一致 options.Audience = "api1"; //token 默認容忍5分鐘過時時間偏移,這裏設置爲0, //這裏就是爲何定義客戶端設置了過時時間爲5秒,過時後仍能夠訪問數據 options.TokenValidationParameters.ClockSkew = TimeSpan.Zero; options.Events = new JwtBearerEvents { //AccessToken 驗證失敗 OnChallenge = op => { //跳過全部默認操做 op.HandleResponse(); //下面是自定義返回消息 //op.Response.Headers.Add("token", "401"); op.Response.ContentType = "application/json"; op.Response.StatusCode = StatusCodes.Status401Unauthorized; op.Response.WriteAsync(JsonConvert.SerializeObject(new { status = StatusCodes.Status401Unauthorized, msg = "token無效", error = op.Error })); return Task.CompletedTask; } }; });
Configure()api
app.UseStaticFiles(); //這裏注意 必定要在 UseMvc前面,順序不可改變 app.UseAuthentication(); app.UseCors("client1");
能夠看到右側console 再自動刷新瀏覽器