0

如何限制每个客户端应用程序上的 x 登录次数,特别是具有授权类型的 SPA 客户端 - 隐式

这超出了身份服务器的范围

尝试的解决方案 -

  1. 访问令牌持久保存到数据库,但是这种方法客户端不断更新访问令牌而无需编写代码,因为客户端浏览器请求带有一个有效令牌,尽管它已过期,静默身份验证通过发出新的参考令牌来更新令牌(可以在表中可以看到persistGrants token_type 'reference_token')

  2. Cookie 事件 - 在 validateAsync 上 - 虽然这仅适用于服务器 Web,但运气不佳,我们不能将此逻辑放在 SPA 客户端的 oidc 库中。

  3. 通过覆盖 SignInAsync 自定义 signInManager - 但在调试模式下执行未达到这一点,因为 IDM 不断识别用户具有有效的令牌(虽然已过期)不断重新发出令牌(请注意这里没有刷新令牌来管理它通过存储和修改!!!)

即使访问令牌已过期,IDM 如何在不带用户进入登录屏幕的情况下重新颁发令牌的任何线索??(静默身份验证。??

4

1 回答 1

1

实现配置文件服务覆盖 activeasync

  public override async Task IsActiveAsync(IsActiveContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await userManager.FindByIdAsync(sub);

        //Check existing sessions
        if (context.Caller.Equals("AccessTokenValidation", StringComparison.OrdinalIgnoreCase))
        {
            if (user != null)
                context.IsActive = !appuser.VerifyRenewToken(sub, context.Client.ClientId);
            else
                context.IsActive = false;
        }
        else
            context.IsActive = user != null;
    }

启动

services.AddTransient<IProfileService, ProfileService>();

同时将身份服务器服务添加到配置服务下的集合

 .AddProfileService<ProfileService>();

更新

Session.Abandon(); //is only in aspnet prior versions not in core
Session.Clear();//clears the session doesn't mean that session expired this should be controlled by addSession life time when including service.

我碰巧找到了一种更好的方法,即使用 aspnetuser securitystamp,每次用户登录时都会更新安全标记,这样任何先前的活动会话/cookie 都会失效。

_userManager.UpdateSecurityStampAsync(_userManager.FindByEmailAsync(model.Email).Result).Result

更新(最终):

登录时:-

var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberLogin, false);
                if (result.Succeeded)
                {
            //Update security stamp to invalidate existing sessions           
                    var user = _userManager.FindByEmailAsync(model.Email).Result;
                    var test= _userManager.UpdateSecurityStampAsync(user).Result;
                    //Refresh the cookie to update securitystamp on authenticationmanager responsegrant to the current request
                    await _signInManager.RefreshSignInAsync(user);
          }

配置文件服务实施:-

public class ProfileService : ProfileService<ApplicationUser>

{
public override async Task IsActiveAsync(IsActiveContext context)
        {
            if (context == null) throw new ArgumentNullException(nameof(context));
            if (context.Subject == null) throw new ArgumentNullException(nameof(context.Subject));

            context.IsActive = false;

            var subject = context.Subject;
            var user = await userManager.FindByIdAsync(context.Subject.GetSubjectId());

            if (user != null)
            {
                var security_stamp_changed = false;

                if (userManager.SupportsUserSecurityStamp)
                {
                    var security_stamp = (
                        from claim in subject.Claims
                        where claim.Type =="AspNet.Identity.SecurityStamp"
                        select claim.Value
                        ).SingleOrDefault();

                    if (security_stamp != null)
                    {
                        var latest_security_stamp = await userManager.GetSecurityStampAsync(user);
                        security_stamp_changed = security_stamp != latest_security_stamp;
                    }
                }

                context.IsActive =
                    !security_stamp_changed &&
                    !await userManager.IsLockedOutAsync(user);
            }
        }
    }   

*

挂钩服务集合:-

*

services.AddIdentityServer()
    .AddAspNetIdentity<ApplicationUser>()                
         .AddProfileService<ProfileService>();

即在每次登录时,用户的安全标记被更新并推送到cookie,当令牌过期时,授权端点将验证安全更改,如果有则重定向用户登录。通过这种方式,我们确保只有一个活动会话

于 2017-09-04T00:25:22.553 回答