用户中心

背景

很早之前就想做一个用户统一登陆的系统,即“统一身份认证”。这就需要将用户的账号、密码存储在同一个系统中,然后下属的各个系统调用“统一身份认证”,验证密码是否正确。
但是这只是做到了身份认证,用户信息还是需要各个子系统单独维护的,这样一来用户的信息又需要填写多遍,也就没带来多大便利了。
于是就想干脆做大点,将各个系统中的通用模块独立出来,比如用户、角色、权限等,这样子系统中就不需要这些重复模块,直接调用接口获取数据就行,于是“用户中心”应运而生。

设计

SSO

参考了很多现有的统一管理系统,SSO (Single-Sign-On) 即单点登录,通过一次登陆实现各个系统的全部登陆。

如果所有产品都是在同一主域下,那么只要把登录的标识信息存放到主域的 session 中,通过数据库或者 cache 共享,即可实现访问任一产品的页面时把登录信息传递到服务器,然后服务器根据该信息判断是否需要用户再次登录。

虽然大多数公司的产品都是在同一个域名下,但有些还是独立域名的,这时就涉及到跨域问题,也是 SSO 的难点所在。

基本思路是在一个固定的入口登录,成功后返回一个 token,将这个 token 附带在跨域访问的某个文件上,该文件拿到这个 token 和服务器上存放的值比较,并获取对应的登录用户信息,然后设置登录标识,以此完成 SSO 登录。服务器上的 token 可以存在 redis 等缓存中,或者通过 RPC 访问。

可以用 iframe 登录,然后在 iframe 中跳转来达到通过同一入口进行登录。难点在于跨域,特别需要注意的是:

iframe 中的 js 如果要访问父窗口的方法,需要保证域名相同,或者主域相同并都设置domain属性为主域地址,否则浏览器会报安全警告。

跨域只要发起跨域的http请求即可,可以放到 script 标记的src中,也可已放到图片对象的 src 中,推荐后者,因为后者不用放到dom节点中。需要注意的是,这两种方式都要带一个每次都不同的参数,可以是时间戳,以防止浏览器的自动缓存。

OAuth2.0

OAuth是一种授权协议,只是为用户资源的授权提供了一个安全的、开放而又简易的标准。OAuth 2.0为开发者开发Web应用,桌面端应用程序,移动应用提供特定的授权流程。

OAuth是为解决不同公司的不同产品实现登陆的一种简便授权方案,通常这些授权服务都是由大客户网站提供的,如QQ,微博,微信等。而使用这些服务的客户可能是大客户网站,也可能是小客户网站。使用OAuth授权的好处是,在为用户提供某些服务时,可减少或避免因用户懒于注册而导致的用户流失问题。

OAuth2.0提供四种授权模式
(1)授权码模式(authorization_code)
授权码是OAuth2.0中常用的模式,通过认证服务器授权后方可访问第三方应用程序,主要流程如下:

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

(2)密码模式(password)
密码模式用于非PC或WAP端的身份认证,如:APP登陆。

(3)客户端模式(client_credentials)
客户端模式用于未登陆时的接口授权,此时只能访问不需要登陆的接口,如:注册时的发送验证码。

(4)简化模式(implicit)
简化模式(implicit)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤。

DB

包含基本的users、permissions、roles等;apps为主表,存储所有接入的应用,各permissions中包含app_id外键,指向apps中的id主键。

用户中心提供服务的粒度都是某个具体的应用,子系统拿申请的 client_id 和 client_secret 获取access_token,通过access_token 访问用户中心数据,比如获取用户信息。

具体的API文档见http://yaoshanliang.github.io/ucenter-open/

实现

技术
  • 读写分离

  • redis缓存

  • 日志、短信、邮件队列

  • 微信登陆

功能
  • 用户统一管理
  • 统一身份认证
  • 角色统一管理
  • 权限统一管理
  • 日志服务
  • 短信服务
  • 邮件服务
  • 文件服务

附:
演示地址, 源码
开放平台, 源码
OAuth2.0接入

Just a beginner.<br /><a href='https://about.iat.net.cn' target='_blank'>profile</a>