用户服务


layout: docs-default

用户服务

用户服务的例子,请看这里

IdentityServer3 定义了一个 IUserService 接口来抽象下层的用户身份管理系统,它为本地和第三方账号的用户验证语义,它也提供了IdentityServer生成令牌需要的身份和声明以及用户信息endpoint.用户服务更提供了登陆的工作流(比如接受用户许可协议或者登陆额外需要的2fa)

用户服务的方法分为认证相关方法和令牌声明信息和用户信息相关方法。

  • 用户试图登陆时,IdentityServer调用认证方法来认证。这些方法的输出或者是成功登陆,错误或部分登陆(本节后面会详细介绍部分登陆)
  • 当IdentityServer需要声明信息或确认用户还有权获取令牌时,会调用用户信息相关方法。

IUserService

IUserService 定义了下面的方法:

  • PreAuthenticateAsync
    • 这个方法在现实登陆页面前调用,用来判断用户是否已经被其它方式认证(比如客户端证书或者可信HTTP 头),如果已经登陆,那么登陆页面不会显示。
    • PreAuthenticationContext 有下面的属性:
      • SignInMessage: 登陆的上下文信息
      • AuthenticateResult: 用户服务判定如何显示认证(如果是null则显示正常的登陆界面。)
      • ShowLoginPageOnErrorResult (v2.4新增): 如果AuthenticateResult含有一个错误信息,我们希望它把错误信息显示在登陆页面(而不是一个通用错误信息)。
  • AuthenticateLocalAsync
    • 这个方法用于本地账号登陆 (只要用户使用用户名密码对话框登陆).
    • LocalAuthenticationContext 有下面的属性:
      • Username: 用户名.
      • Password: 密码.
      • SignInMessage: 授权endpoint收到的上下文信息.
      • AuthenticateResult: 用户服务判定如何显示认证(如果是null表示无效的 UsernamePassword).
  • AuthenticateExternalAsync
    • 用户使用第三方认证的时候,会调用这个方法来关联第三方账号和本地账号。
    • ExternalAuthenticationContext 有下面的属性:
      • ExternalIdentity: 第三方登陆提供的信息,包括:
        • Provider: 第三方登陆的标识符.
        • ProviderId: 第三方登陆提供的用户唯一标识。
        • Claims: 第三方登陆提供的用户声明信息。
      • SignInMessage: 授权endpoint收到的上下文信息.
      • AuthenticateResult: 用户服务判定如何显示认证(如果是null表示没有本地账号能匹配上第三方提供的账号).
  • PostAuthenticateAsync
    • 这个方法在用户登陆成功但是还没有转到客户程序时调用。在所有其他认证结束后,用户服务在这里确认自定义工作流
    • PostAuthenticationContext 带有下面属性:
      • SignInMessage: 授权endpoint收到的上下文信息.
      • AuthenticateResult: 当前的 AuthenticateResult. 用户服务可以修改这个值来改变认证输出。
  • SignOutAsync
    • 用户登出时调用这个方法
    • SignOutContext 带有下面属性:
      • Subject: 登出用户的标识
  • GetProfileDataAsync
    • 当申请任何声明时,这个方法会被调用(如: 创建令牌时或者来自用户信息endpoint).
    • ProfileDataRequestContext 带有下面属性:
      • Subject: 被请求的用户信息的用户标识
      • IssuedClaims: 用户服务需要赋值给这个属性来指定那些声明可以下发。
      • RequestedClaimTypes: 请求的声明类型。用户服务只能返回这个属性指定的声明。
      • AllClaimsRequested: 请求返回所有声明(这个属性会忽略RequestedClaimTypes).
      • Client: 那个客户端发出的请求
      • Caller: IdentityServer 中那个方法调用了当前方法,可能的值包括:
        • "ClaimsProviderIdentityToken"
        • "ClaimsProviderAccessToken"
        • "UserInfoEndpoint"
  • IsActiveAsync
    • 这个方法用于判断用户是否还是有效的,活跃的。(比如:用户登陆期间,账号可能已经被禁用啦).
    • IsActiveContext 带有下面属性:
      • Subject: 用户标识.
      • Client: 那个客户端发出的请求.
      • IsActive: 如果用户已经被禁用,用户服务应该设置这个值为false。

SignInMessage

所有的认证方法都会收到SignInMessage上下文信息:

  • ReturnUrl: 用户从这个Url发起登陆请求,一般意味着,登陆成功后需要返回到这个页面。
  • ClientId: 发出登陆请求的客户端的标识
  • IdP: 第三方登陆提供请求
  • Tenant: 用户来自哪个承租人。
  • LoginHint: 登陆时期望的用户名,可以默认显示登陆页面用户名输入框。
  • DisplayMode: 来自授权请求的显示模式。
  • UiLocales: UI本地化要求。
  • AcrValues: 来自授权请求的acr值

AuthenticateResult

所有的认证方法都会返回AuthenticateResult,它有很多可能的输出结果。它有多个构造函数来初始化不同的输出:

// Full login
AuthenticateResult(string subject, string name, IEnumerable<Claim> claims = null, string identityProvider = Constants.BuiltInIdentityProvider, string authenticationMethod = null)

// Partial Login (where subject is known)
AuthenticateResult(string redirectPath, string subject, string name, IEnumerable<Claim> claims = null, string identityProvider = Constants.BuiltInIdentityProvider, string authenticationMethod = null)

// Partial Login (where subject is not known)
AuthenticateResult(string redirectPath, IEnumerable<Claim> claims)

// Partial Login (from external login)
AuthenticateResult(string redirectPath, ExternalIdentity externalId)

// Login error
AuthenticateResult(string errorMessage)

完整登陆

完整登陆必须提供用户的subjectnamesubject是用户服务使用的用户唯一标识,name用来显示在用户界面上。
声明(Claim)也可能提供,用户服务的有些方法可能需要这些附加的信息。
如果是通过第三方登陆,那么identityProvider参数也需要提供。这个参数可以通过身份令牌里的idp声明提供或者用户信息endpoint. 如果通过本地账号登陆,这个参数不应该被使用(会使用默认的Constants.BuiltInIdentityProvider ).

可选参数 authenticationMethod生成amr声明,用来说明用户该如何验证,如:双因子验证还是客户端证书验证。如果没有传入,那么本地账号期望使用password,如果是第三方登陆,那么这个值会是external表示是第三方登陆。
所有这些声明(subject, name, idp, amr 和其他Claim列表)会用来生成认证cookie。这个认证cookie会由katana cookie认证中间件来管理。认证中间件会使用常量Constants.PrimaryAuthenticationType来设定AuthenticationType值。

ClaimsPrincipal由完整登陆创建,IUserService其它API会通过Subject使用。(PostAuthenticateAsync, GetProfileDataAsync, IsActiveAsync, and SignOutAsync).

部分登陆

除了完整登陆,认证API还可以执行"部分登陆".部分登陆允许用户服务中断用户的正常登陆过程,让用户到一个自定义的页面去完成一些任务后才能继续登陆。(比如完成注册,接受用户许可协议,执行2fa)。、

部分登陆会通过katana认证中间件发送一个"部分登陆的"cookie,认证中间件会使用常量Constants.PrimaryAuthenticationType来设定AuthenticationType值。
部分登陆可以创建和完整登陆一样的参数(subject, name, claims, amr, and idp)以及redirectPath. 部分登陆也可以只创建 claims集合和 redirectPath. 两种方法的最大区别是用户身份已经确认。

托管程序会提供redirectPath,用来重定向到自定义的网页上,在这个网页上用户声明可以用来完成自定义的工作流。这个页面可以通过GetIdentityServerPartialLoginAsync OWIN environment extension method来获取声明信息.

当用户完成了自定义的任务(接受用户许可协议,注册或者2fa), 用户会被重定向会登陆页面完成完整的登陆过程。重定向用户回来的URL可以通过GetPartialLoginResumeUrlAsync OWIN environment extension method方法得到.如果需要用户重新登陆,则调用 GetPartialLoginRestartUrlAsync OWIN environment extension method .

在重定向回登陆页面前,在部分登陆的声明可以通过UpdatePartialLoginClaimsAsync OWIN environment extension method改变.如果需要移除或者清除部分登陆则可以使用RemovePartialLoginCookie OWIN environment extension method.

第三方部分登陆

如果用户从第三方登陆并且没有对应的本地账号。自定义的用户服务也可以重定向会客户端,这需要通过创建一个带有ExternalIdentityAuthenticateResult,并传给AuthenticateExternalAsyncAPI。这会创建一个部分登陆(和上面一样t通过PartialSignInAuthenticationType),但是cookie里会用external_provider_user_id代替subject声明(或者通过Constants.ClaimTypes.ExternalProviderUserId),声明里的Issuer是第三方标识,这个标识可以用来创建本地账号并和第三方账号关联。
一旦用户完成了本地账号注册,他会被重定向会登陆页面来完成完整登陆(和上面机制一样).

登陆错误

最后,认证API可以提供错误信息显示在登陆页面上,这可以通过使用AuthenticateResult的接受字符串(错误信息)构造函数来实现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容