.net core Identity4 SSO 单点登录,联合登出

以.net core为例

认证服务器配置

// 客户端1
new Client {
    ClientId = "mvc1",
        ClientName = "客户端1",
        AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

        ClientSecrets = {
            new Secret ("secret".Sha256 ())
        },

        // 登录地址
        RedirectUris = { "http://localhost:5002/signin-oidc" },
        // 登出回调地址
        PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
        // 联合登出地址
        FrontChannelLogoutUri = "http://localhost:5002/Account/UnionLogout",

        AllowedScopes = {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "api1"
        },
        AllowOfflineAccess = true
},
// 客户端2
new Client {
    ClientId = "mvc2",
        ClientName = "客户端2",
        AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

        ClientSecrets = {
            new Secret ("secret".Sha256 ())
        },

        // 登录地址
        RedirectUris = { "http://localhost:6000/signin-oidc" },
        // 登出地址
        PostLogoutRedirectUris = { "http://localhost:6000/signout-callback-oidc" },
        // 联合登出地址                    
        FrontChannelLogoutUri = "http://localhost:6000/Account/UnionLogout",

        AllowedScopes = {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "api1"
        },
},

客户端1配置(端口5002)

services.AddAuthentication (options => {
        options.DefaultScheme = "Cookies"; // 默认认证使用cookie
        options.DefaultChallengeScheme = "oidc"; // 登录跳转使用oidc
    })
    .AddCookie ("Cookies") // 添加cookie认证方式
    .AddOpenIdConnect ("oidc", options => // 添加oidc认证方式
        {
            options.SignInScheme = "Cookies";

            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;

            options.ClientId = "mvc";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";

            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Scope.Add ("api1");
            options.Scope.Add ("offline_access");
        });

客户端2配置(端口6000)

services.AddAuthentication (options => {
        options.DefaultScheme = "Cookies"; // 默认认证使用cookie
        options.DefaultChallengeScheme = "oidc"; // 默认登录跳转使用oidc
    })
    .AddCookie ("Cookies") // 添加cookie认证方式
    .AddOpenIdConnect ("oidc", options => // 添加oidc认证方式
        {
            options.SignInScheme = "Cookies";

            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;

            options.ClientId = "mvc";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";

            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Scope.Add ("api1");
            options.Scope.Add ("offline_access");
        });

客户端(1和2使用相同的原理)登录方法
配置[options.DefaultChallengeScheme = “oidc”;]指明了未授权的处理方式,所以我们没有登录方法

客户端(1和2使用相同的原理)登出方法

public async Task Logout () {
    await HttpContext.SignOutAsync ("Cookies"); // 执行cookie认证的登出流程
    await HttpContext.SignOutAsync ("oidc"); // 执行oidc认证的登出流程
}

客户端(1和2使用相同的原理)联合登出方法,认证服务器登出会回调该方法

public class AccountController : Controller {
    public async Task UnionLogout () {
        if (User?.Identity.IsAuthenticated == true) {
            await HttpContext.SignOutAsync ("Cookies");
        }
    }
}

关于联合登出,IdentityServer给出的解决方案解析

LogoutRequest logout = await _interaction.GetLogoutContextAsync(logoutId);

LogoutRequest的属性:
SignOutIFrameUrl:联合登出iframe url

前端解析
前端通过iframe载入SignOutIFrameUrl

<iframe width="0" height="0" class="signout" 
src="http://localhost:5000/connect/endsession/callback?endSessionId=CfDJ8MjbRQK-dj1KuWho4RCkRWGAelvl6lAvN_7HoDHOSbvTKZ0wpqzBsemo4K_bX8LTYWeHpa6lnQOkUsARMI5d39XG6UsrZto6dbh_GwYAWmZn3ztfQz6F_GEd2Vhv0gn7CWLrIPgc4E-mZCNZd9jc2S-16EGQWiTcbS5TQt6bn-pIxJq5h4_v15W95Hl7hfAZpXxby1dkHikdlp2ht7KkJX2gh6xemHLRjmv6PJ-DGsTojCZFjeq3x8eaXb8qF89NRS76Pq6vShm6A3alup3FW2rLWc-2xLHvGibbi6TraBha"></iframe>

SignOutIFrameUrl指向的iframe的内容如下

// 客户端2的联合登出地址
<iframe 
src="http://localhost:6000/Account/UnionLogout?sid=95e59530f0f942965dc77e940e3e48d8&amp;iss=http%3A%2F%2Flocalhost%3A5000"></iframe>
// 客户端1的联合登出地址
<iframe 
src="http://localhost:5002/Account/UnionLogout?sid=95e59530f0f942965dc77e940e3e48d8&amp;iss=http%3A%2F%2Flocalhost%3A5000"></iframe>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值