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
表示无效的Username
或Password
).
-
-
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)
完整登陆
完整登陆必须提供用户的subject
和name
,subject
是用户服务使用的用户唯一标识,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.
第三方部分登陆
如果用户从第三方登陆并且没有对应的本地账号。自定义的用户服务也可以重定向会客户端,这需要通过创建一个带有ExternalIdentity
的AuthenticateResult
,并传给AuthenticateExternalAsync
API。这会创建一个部分登陆(和上面一样t通过PartialSignInAuthenticationType
),但是cookie里会用external_provider_user_id
代替subject声明(或者通过Constants.ClaimTypes.ExternalProviderUserId
),声明里的Issuer是第三方标识,这个标识可以用来创建本地账号并和第三方账号关联。
一旦用户完成了本地账号注册,他会被重定向会登陆页面来完成完整登陆(和上面机制一样).
登陆错误
最后,认证API可以提供错误信息显示在登陆页面上,这可以通过使用AuthenticateResult
的接受字符串(错误信息)构造函数来实现。