IdentityServer4授權和認證


IdentityServer4 簡稱ids4

oidc了解:http://www.jessetalk.cn/2018/04/04/oidc-asp-net-core/

是一個去中心化的網上身份認證系統,集成了認證和授權

博客園已經有很多大佬寫過了。我也是跟着學,記錄下學習成果

授權服務器代碼:

var oidc = new Client
            {
                ClientId = "oidc",
                ClientName = "name",
                ClientSecrets = { new Secret("secret".Sha256()) },
                ClientUri = "http://www.cnblogs.com", //客戶端
                LogoUri = "https://www.cnblogs.com/images/logo_small.gif",
                //AllowedGrantTypes={GrantType.AuthorizationCode }

                /*
                 如果客戶端使用的認證是
                 */
                AllowedGrantTypes = GrantTypes.Hybrid,
                AllowedScopes ={
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                    },
                RedirectUris = { "http://localhost:5001/signin-oidc" },
                PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" }
            };

AllowedScopes 中的

IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile必須的

也可以不用枚舉類型。直接寫:“openid”,"profile"

 

為什么說是必須定義的呢。因為ids4代碼的封裝。默認就添加了“openid”,"profile"兩個scope

因為只有openid才能確定唯一性

而profile是用戶資料信息

github地址:

https://github.com/aspnet/AspNetCore/blob/master/src/Security/Authentication/OpenIdConnect/src/OpenIdConnectOptions.cs

 

 可以看到其他的默認配置,比如回調地址,登出地址

如果之前了解過授權和認證,對這個不陌生

//使用ids中間件
app.UseIdentityServer();

 

認證代碼,我自己寫了挺多注釋,可以忽略

  services.AddAuthentication(options =>
            {
                /*
                 要想使用認證系統,必要先注冊Scheme
                 而每一個Scheme必須指定一個Handler
                 AuthenticationHandler 負責對用戶憑證的驗證
                 這里指定的默認認證是cookie認證
                 Scheme可以翻譯為方案,即默認的認證方案

                因為這里用到了多個中間件,(AddAuthentication,AddCookie,AddOpenIdConnect)
                OpenIdConnectDefaults.DisplayName 的默認值是oidc
                指定AddOpenIdConnect是默認中間件,在AddOpenIdConnect配置了很多選項

                如果只用了一個中間件,則可以不寫,是否還記得cookie認證
                //     services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                //     .AddCookie(option =>
                //     {
                //         ///Account/Login?ReturnUrl=%2Fadmin
                //         option.LoginPath = "/login/index";
                //         //option.ReturnUrlParameter = "params"; //指定參數名稱
                //         //option.Cookie.Domain
                //         option.AccessDeniedPath = "/login/noAccess";
                //         option.Cookie.Expiration = TimeSpan.FromSeconds(4);
                //         option.Events = new CookieAuthenticationEvents
                //         {
                //             OnValidatePrincipal = LastChangedValidator.ValidateAsync
                //         };
                //     });

                 */

                //options.DefaultScheme = "Cookies";

                //默認的認證方案:cookie認證,信息是保存在cookie中的
                options.DefaultAuthenticateScheme = "Cookies";
                //oidc 就是openidConnect


                //名字隨便取,只要AddOpenIdConnect中的的oidc名字一樣即可,
                //這樣才能找到
                options.DefaultChallengeScheme = "oidc";

                //默認使用oidc中間件
                //options.DefaultChallengeScheme = OpenIdConnectDefaults.DisplayName;


            }).AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = "http://localhost:5003";
                options.RequireHttpsMetadata = false;
                options.ClientId = "oidc";
                options.ClientSecret = "secret";
                options.SaveTokens = true;
                //options.Scope.Add("openid");
                /*
                 默認值是:id_token
                 */
                //options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                options.Events = new OpenIdConnectEvents
                {
                    /*
                     遠程異常觸發
                     在授權服務器取消登陸或者取消授權      
                     */
                    OnRemoteFailure = OAuthFailureHandler =>
                    {
                        //跳轉首頁
                        OAuthFailureHandler.Response.Redirect("/");
                        OAuthFailureHandler.HandleResponse();
                        return Task.FromResult(0);
                    }
                };
            });
View Code

 

配置其實跟OAuth2認證差不多,運行是沒有問題的

我這里主要講解ids4的授權和認證類型ResponseType

默認是 id_token ,源碼是個好東西,我們看看

 

 

客戶端端id_token對應服務端,會返回id_token

AllowedGrantTypes = GrantTypes.Implicit, 隱式模式

 

它返回id_token信息,包含了用戶信息的SubjectId,是TestUser配置的

參考:https://www.cnblogs.com/jesse2013/p/oidc-in-aspnetcore-with-identity-server.html

 

客戶端端code id_token對應服務端,會返回id_token和access_token

AllowedGrantTypes = GrantTypes.Hybrid, 混合模式

 可以用access_token 去userinfo endpoint獲取用戶信息

access toke管的是權限,里面保存的是一些認證信息

,id token是身份信息

 

 

 

 

 http://localhost:5003/.well-known/openid-configuration 

可以查看userinfo endpoint配置

 

 

有人可能會注意到,在這里我們拿到的idtoken沒有派上用場,我們的用戶資料還是通過access_token從userinfo endpoint里拿的。這里有兩個區別:

  1. userinfo endpoint是屬於認證服務器實現的,並非資源服務器,有歸屬的區別
  2. id_token 是一個jwt,里面帶有用戶的唯一標識,我們在判斷該用戶已經存在的時候不需要再請求userinfo endpoint

下圖是對id_token進行解析得到的信息:sub即subject_id(用戶唯一標識 )

 

 

 

 

 看網上很多例子都在Controller上打個Authorize標簽

當未授權就跳轉到授權服務器,這樣,這個網站那就必須使用授權服務器才能登陸

比如:我這個網站可以有自己的密碼登陸,也可以用第三方登陸。所以在沒有授權的時候是跳轉到登陸頁面,

讓用戶自己選擇是密碼登陸還是第三方授權登陸

 

 如果是這樣,我沒有授權登陸。只有訪問這個Admin頁面就會跳轉到授權服務器,

那如果我們添加多個第三方認證,比如QQ,微博,微信等等,那起步亂套了

顯然這不是我想要的,應該像簡書這樣,集成第三方登陸

 

 

 

所以我們可以設置使用那個中間件options.DefaultChallengeScheme=“myCookies

當沒有登陸的是,會走AddCookie,跳轉到到登陸頁面

比如我們這里注入了oidc授權,google授權

 services.AddAuthentication(options =>
            {

                //默認的認證方案:cookie認證,信息是保存在cookie中的
                options.DefaultAuthenticateScheme = "Cookies";
              
               
                options.DefaultChallengeScheme = "myCookies";


            }).AddCookie("myCookies",options=> {
                options.LoginPath = "/Account/Login";
            })
            .AddGoogle("googole", options => {
               
            })
            .AddOpenIdConnect("oidc", options =>
            {
            }

 

當用戶單擊,使用微博登陸則:通過Challenge方法指定使用那個schemes

 

 這樣就會跳轉到登陸頁面,用戶自己選擇了

 

可以用User.Identity.IsAuthenticated判斷是否驗證授權
沒有則手動觸發: Challenge("oidc")
oidc 為你想使用的第三方
比如:我設置了,cookie,微博,QQ,google,oidc等等
.AddCookie("cookie")
.AddGoogole("google")
.AddQQ("qq")
當你想用google授權,則Challenge(”google")

這樣做的好處是:我網站只是接入別第三方登陸。至於使用第三方登陸還是使用我網站注冊用戶登陸
都是由用戶選擇

 

網絡收集,沒有一一驗證:

/***********************************相關事件***********************************/
    // 未授權時,重定向到OIDC服務器時觸發
    //o.Events.OnRedirectToIdentityProvider = context => Task.CompletedTask;

    // 獲取到授權碼時觸發
    //o.Events.OnAuthorizationCodeReceived = context => Task.CompletedTask;
    // 接收到OIDC服務器返回的認證信息(包含Code, ID Token等)時觸發
    //o.Events.OnMessageReceived = context => Task.CompletedTask;
    // 接收到TokenEndpoint返回的信息時觸發
    //o.Events.OnTokenResponseReceived = context => Task.CompletedTask;
    // 驗證Token時觸發
    //o.Events.OnTokenValidated = context => Task.CompletedTask;
    // 接收到UserInfoEndpoint返回的信息時觸發
    //o.Events.OnUserInformationReceived = context => Task.CompletedTask;
    // 出現異常時觸發
    //o.Events.OnAuthenticationFailed = context => Task.CompletedTask;

    // 退出時,重定向到OIDC服務器時觸發
    //o.Events.OnRedirectToIdentityProviderForSignOut = context => Task.CompletedTask;
    // OIDC服務器退出后,服務端回調時觸發
    //o.Events.OnRemoteSignOut = context => Task.CompletedTask;
    // OIDC服務器退出后,客戶端重定向時觸發
    //o.Events.OnSignedOutCallbackRedirect = context => Task.CompletedTask;
View Code

 

當用戶沒有授權,跳轉到授權服務器的登陸地址,同意授權地址,都是默認值

https://github.com/IdentityServer/IdentityServer4/blob/63a50d7838af25896fbf836ea4e4f37b5e179cd8/src/Constants.cs

 

 

我們可以修改自己想要的地址

 

 

 然后添加Route

 

 這樣就成功了

 

 

大佬文章:

https://www.cnblogs.com/jesse2013/p/oidc-in-aspnetcore-with-identity-server.html

https://www.cnblogs.com/RainingNight/p/7635534.html

https://www.cnblogs.com/xishuai/p/6274036.html

https://www.cnblogs.com/cgzl/p/9253667.html

https://cloud.tencent.com/developer/article/1048128

https://www.cnblogs.com/stulzq/p/7879101.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM