
场景1: 用户未登录情况下访问受限资源:
1. 用户通过浏览器访问受限资源:x.xxxx.com/private/xxx…,配置在应用端的过滤器:AuthenticationFilter过滤请求,发现是受限访问资源,于是判断当前用户是否登录,判断分两步进行,先判断是否有AuthId cookie。如果有,则根据Authid(为键)在Redis中查找用户信息,如果有对应的用户信息,则说明用户已经登录,放行访问目标资源,并对当前request进行wrapper,以让应用可以通过request.getRemoteUser() 获取当前用户信息(会员ID)。
2. 如果没有AuthId cookie或者Redis没有找到用户信息,则将用户重定向到passport.xxxx.com进行登录,重定向url为:https://passport.xxxx.com/ids/login?service=https://x.xxxx.com/auth?targetUrl=http://x.xxxx.com/private/xxx.html ,其中https://passport.xxxx.com/ids/login 是passport.xxxx.com的登录服务地址,service参数https://x.xxxx.com/auth?targetUrl=http://x.xxxx.com/private/xxx.html 是登录完成后重定向回web应用的地址。
3. passport.xxxx.com显示登录页面,用户输入用户名、密码(和图形校验码)并提交。系统基于会员系统提供的认证接口验证用户输入的用户名密码是否正确。
4. 在验证通过后,passport.xxxx.com向浏览器设置tgt cookie,该cookie为一串随机串,标识当前用户在passport.xxxx.com已登录。
5. passport.xxxx.com将浏览器重定向到https://x.xxxx.com/auth?targetUrl=http://x.xxxx.com/private/xxx.html并带上ticket参数,即:https://x.xxxx.com/auth?targetUrl=http://x.xxxx.com/private/xxx.html&ticket=xxxxxxxxxxxx ,ticket是passport.xxxx.com为本次重定向生成的一次性票据,web应用获取到该票据后凭借该票据和passport.xxxx.com交换当前用户信息。 https://x.xxxx.com/auth 对应web应用中的AuthenticationServlet,该servlet在ids-client.jar中提供,并且以https的形式开放,以保障票据传输过程的安全。
6. 在web应用端,AuthenticationServlet从request中取出ticket参数,通过HttpClient访问:https://passport.xxxx.com/ids/serviceValidate?ticket=xxxxxxxx,来验证ticket票据是否合法,passport.xxxx.com验证该票据是否合法,验证通过后在response中写入当前用户信息(会员ID)和SessionIdentifier(随机串,作为AuthId cookie的值,并且用于单点登出),并且,立刻将该票据销毁,以防止重放攻击。并且,如果该票据在颁发后20秒内还没有被验证,也会被销毁,以加强票据的安全性。
7. AuthenticationServlet解析出response中的当前用户信息,并取出SessionIdentifier作为AuthId写入cookie,cookie的域为应用所在的大域,如 .xxxx.com。同时将AuthId、用户信息写入Redis缓存。
8. AuthenticationServlet将浏览器重定回targetUrl,即用户最初要访问的受限资源:http://x.xxxx.com/private/xxx.html,于是回到第1.步,因为先前已经将用户的登录状态通过AuthId cookie和Redis保存,AuthenticationFilter将放行访问目标资源,至此完成了一次登录请求过程。
场景2:用户在访问站点A时,已经成功登录,这时候用户再去访问与站点A同域下的站点B
例如: 用户在站点A http://x.xxxx.com/ 登录成功了,这时候用户再去访问站点http://y.xxxx.com/ 下的受限资源。/private/a.do
由于用户在站点A登录了,那么在 .xxxx.com 域下一定存在AuthId的cookie,并且Redis中一定保存了用户的登录信息。当用户访问web应用B的受限资源时,web应用B的AuthenticationFilter能够读取到.xxxx.com域下的AuthId的cookie,并可以从Redis获取到用户登录信息,因此AuthenticationFilter判断该用户已经登录,放行本次访问。
场景3:用户在访问站点A时登录成功,这时候用户再去访问与站点A不同域下的站点C。
例如: 用户在站点A http://x.xxxx.com/ 登录成功了,这时候用户再去访问web应用C http://a.xxxx.com/ 下的受限资源 /private/a.do,web应用C的AuthenticationFilter检查用户是否登录,即首先检查 .payxxxx.com 域下是否有Authid Cookie,此时,虽然在.xxxx.com下存在AuthId cookie,但是因为是跨域,应用C无法获得.xxxx.com下的cookie,于是AuthenticationFilter将请求重定向到passport.xxxx.com进行登录。因为用户已经在passport.xxxx.com登录了,这时不会再跳转到登录页要求用户登录,而是直接重定向回web应用C,后续过程同场景1。
用户可以在任何 web应用点击登出链接,链接指向https://passport.xxxx.com/ids/logout,passport.xxxx.com接受到注销请求后,执行自身的会话注销(清除tgt cookie和server端对应的会话状态)。并且,通过HttpClient通知所有曾经颁发过票据(ticket)的web应用进行登录状态的清除。方式是请求各应用的https://app/auth,参数中包含之前生成的SessionIdentifier,web应用中的AuthenticationServlet在接受到SessionIdentifier后,清除redis中以SessionIdentifier为键的用户信息。当用户再次访问应用时,Ids-client检测到用户已经登出,会注销web应用的本地HttpSession。
请求https://passport.xxxx.com/ids/logout进行注销后,默认是跳转到http://www.xxxx.com,若应用需要跳转到指定的登出后页面,则在请求https://passport.xxxx.com/ids/logout时带上service参数,该参数值为指定的登出后页面的url。
1.用户打开应用,显示登录界面。用户输入用户名、密码后,POST方式提交请求至passport.xxx.com/ids/login?j…验证登录信息,提交的参数包括:用户名参数为username,密码参数为password,验证码参数为verifyCode,验证码uuid参数为uuid,验证成功后重定向的地址参数为service。(service=https://appServer/context/auth?targetUrl=http://appServer/context/myloginxx.htm)
终端通过httpClient提交Post请求,service的targetUrl部分设置为应用Server的登陆初始化Url。
2.若验证成功,则在passport.xxx.com域下写cookie(TGC)并重定向到到service指定地址,完成应用server
终端保存该cookie,并设置重定向;
端登录凭证的校验和登录状态的建立(包括写应用server端redis和写客户端cookie值authId)。若登录凭证
终端保存该cookie;
校验成功,则重定向到service中targetUrl部分,此处需要带上appServer域下的cookie值(authId),在该targetUrl
终端设置重定向,设置cookie;
请求中完成应用server端需要做的初始化操作。若登录凭证校验失败,则重定向到passport.xxx. com
应用server在targetUrl指向的地址中完成用户的初始化(CustNum通过request.getRemoteUser()获取,用户名在targetUrl部分带在请求上);
/ids/login登录页面,终端应用程序应能够探测返回的响应头(response header),如果响应头中包含
终端判断响应头中是否包含passport.login.flag,并做相应处理;
passport.login.flag,则表示需要登录,终端应用需要显示登录界面让用户登录。
3.若校验失败,则返回json串{"errorCode": "xxxx", "needVerifyCode":xxxx }。ErrorCode值见附录5.2。needVerifyCode值为true或false,即是否需要验证码。终端应用需要根据这些错误码再次显示登录界面让用户登录。(当errorCode为badPassword.msg1、badPassword.msg2或badPwdOfNotBindingMemberCard.msg1、badPwdOfNotBindingMemberCard.msg2时,json串中会包含密码输错剩余次数"remainTimes":数字)
终端根据返回的errorcode做相应处理;
用户登录后,长时间不操作状态过期,继续访问受限资源
1.访问受限资源,拦截器判断出无该用户登录状态,将该请求重定向到passport.xxx.com/ids/login地址,并带上passport.xxx.com域下的cookie值(TGC)。若passport server端用户状态未过期,则重复“一、打
终端设置重定向,设置cookie;
开应用直接登录”中的第二步,再次重定向到应用server端来写状态,然后再重定向到该受限资源的url。
终端设置重定向,设置cookie;
若passport server端用户状态已过期,则给终端返回登陆页面,此时终端应用程序应探测返回的响应头(response header),如果响应头中包含passport.login.flag,则表示需要登录,终端应用需要显示登录界面让
终端判断响应头中是否包含passport.login.flag,并做相应处理;
用户登录。
登出步骤
1. 请求passport.xxx.com/ids/logout?…值(TGC),则在passport的server端完成用户登陆状态的清除,并重定向
终端设置重定向,设置cookie;
到应用的server端来进行应用的logout逻辑(若不需要此步,则可以不用带上service参数,并且终端不处理本次响应)。