用户基本操作

基础工具

加密

RSA:非对称加密,有公钥和私钥之分,公钥用于数据加密,私钥用于数据解密。加密结果可逆,公钥一般提供给外部进行使用,私钥需要放置在服务器端保证安全性。特点:加密安全性很高,但是加密速度较慢

AES: Advanced Encryption Standard 高级加密标准,最常见的对称加密算法,即加密和解密使用同样的密钥,加密结果可逆,特点:加密速度非常快,适合经常发送数据的场合。

MD5加密:单向加密算法特点:加密速度快,不需要秘钥,但是安全性不高,需要搭配随机盐值使用。

全局异常处理

用户认证

HTTP 无状态协议,需要额外的配置实现状态保存。

是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上,用于告知服务端前后两个请求是否来自同一浏览器。本地保存别人可以分析存放在本地的COOKIE并进行COOKIE欺骗。

session

基于 cookie 实现的一种认证方式,主要作用就是通过服务端记录用户的状态。服务器端接受客户端请求后,建立一个session,并发送一个http响应到客户端,在响应中包含sessionId,客户以cookie的方式保存sessionId,在客户端发起的第二次请求时,浏览器会自动在请求头中带上cookie,服务器根据cookie找到session恢复数据环境。随着用户的增多,服务端压力增大。分布式下拓展性不强,粘性会话 Sticky Session:尽量让同一个用户的请求落到一台机器上。缺点:如果当前机器下线则用户的信息全部丢失。会话复制 Session Replication:将会话信息复制到所有机器上,无论用户请求落到哪台机器上都能取到之前的会话信息。缺点:复制需要成本,冗余过大,难以保证所有机器上会话信息一致。集中会话 Centralized Session:JDBC、Redis等集中保存信息,机器需要信息时到JDBC,Redis中取。

CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

受害者登录a.com,并保留了登录凭证(Cookie)->攻击者引诱受害者访问了b.com->b.com 向 a.com 发送了一个请求:a.com/act=xx->浏览器会默认携带a.com的Cookie->a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求->a.com以受害者的名义执行了act=xx->攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

解决方法:1,同源检测:CSRF大多来自第三方网站,那么就直接禁止外域(或者不受信任的域名)对我们发起请求。2,CSRF Token:攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击。

token

类似于无状态的临时的证书签名,由uid+time+sign[+固定参数]组成,服务端验证浏览器携带的用户名和密码,验证通过后生成用户令牌(token)并返回给浏览器,浏览器再次访问时携带token,服务端校验token并返回相关数据。服务端不用存放 token 数据,用解析 token 的计算时间换取 session 的存储空间,减轻服务器存储压力。安全性高,分布式系统下扩展性强。

JWT

全称是JSON Web Token,用于在空间受限环境下安全传递“声明”,JWT跨语言支持、便于传输、易于扩展。JWT分成三部分,头部(header:声明的类型、声明的加密算法),第二部分是载荷(payload:存放有效信息,一般包含签发者、所面向的用户、接受方、过期时间、签发时间以及唯一身份标识,防篡改,不防泄露),第三部分是签名(signature:主要由头部、载荷以及秘钥组合加密而成)。

缺点:用户状态变化(删除,禁用,注销等)影响到业务而Token仍然有效时,仍然能利用token完成认证,当token过期后需要用户重新登录,用户体验差。

解决办法使用 accessToken (负责后端业务验证)+ refreshToken(负责续签验证)。认证后返回 accessToken + refreshToken,并保存在本地,服务端保存refreshToken,accessToken 失效时间应该设置较短,比如10分钟,refreshToken 失效时间可以长一点,比如 7 天。请求时只用 accessToken,客户端在 accessToken 在失效前主动发起请求用 refreshToken 返回一个新的 accessToken,或者在正常业务请求时判断access-token是否过期,过期了就顺带更新,用户无感提高用户体验。退出时客户端删除accessToken + refreshToken,服务端删除refresh-token。

2b52ac84196749e0a23e2b2b5e0fbc29

注册与登录

数据库表设计

用户表t_user、用户信息表t_user_infot_user在登陆时手机号经常被查询所以对phone建立索引。t_user_info使用useId作为外键,建立与表t_user的联系,根据用户ID获取用户信息时userId经常被查询,所以添加索引。t_refresh_token用于保存用户的refresh_token

用户注册

双方使用RSA对密码加解密,以注册时间为salt,salt与原始密码使用MD5算法构建签名,构建User存入user表。同时构建UserInfo存入user_info表。

用户登录

将收到密码解密后,与数据库中相同手机号的用户的salt构建签名,再将签名与数据库中签名比较以完成认证。成功后根据用户ID生成accessToken,refreshToken返回给用户用于后续请求认证,同时将refreshToken保存在数据库中用于后续刷新accessToken

登录成功后获得token

登陆后获得用户信息

登陆后信息获取依赖accessToken完成认证,在请求头中添加token信息,服务器获取从请求头获得token后解密获得用户ID,完成认证,避免再次登录。最后根据用户ID从数据库中找到并返回用户信息。

请求、响应报文
用户更新

服务器获取从请求头获得accessToken后解密获得用户ID,完成认证。更新时先将新密码和salt构建新签名,再更新其它信息。注意:用户上传信息可能只包含被更改信息,未更改信息字段为空,在更新时需要判空, mybatis下判断user下各个字段,非空下才更新,防止数据丢失。UserInfo的更新同理。

更新access-token

客户端在 accessToken 在失效前主动发起请求用 refreshToken返回一个新的 accessToken,或者在正常业务请求时判断accessToken是否过期,过期了就顺带更新,用户无感提高用户体验。

更新acciss0-token后客户端收到新的access-token