数据表结构设计
关系设计 java
为何不用外键? 分库分表有外键会很是麻烦,清洗数据也很麻烦。数据库内置触发器也不适合采用。mysql
查业务问题的后悔药——时间戳 create_time 数据建立时间 update_time 数据更新时间 能够用于查询业务,主要要存储datetime类型。算法
用户模块
用户表 sql
create table mmall_user( id int(11) PRIMARY key not null auto_increment comment '用户表id', username varchar(50) not null comment '用户名', password varchar(50) not null, email varchar(50) DEFAULT null, phone varchar(50) DEFAULT null, question VARCHAR(100) DEFAULT null, answer varchar(100) DEFAULT null, role int(4) not null, create_time datetime not null, unique key user_name_unique (username) using btree )engine=INNODB auto_increment=21 DEFAULT charset=utf8
用户名username设置为惟一索引unique 因为用户名是不能重复的,在并发的时候能够经过锁的形式解决,可是当架构变成分布式后,经过数据库底层的unique key惟一索引,交给mysql完成了惟一的验证。数据库
涉及知识点
- 横向越权、纵向越权安全漏洞
横向越权:攻击者尝试访问与他拥有相同权限的用户的资源 纵向越权:低级别攻击者尝试访问高级别用户的资源缓存
- 高复用服务响应对象的设计思想及抽象封装
- MD5明文加密及增长salt值
关于MD5网上又不少资料,是一个安全得散列算法,虽然过程不可逆,可是仍是能够经过穷举法获取原值 增长salt值(加盐值)能够必定程度上解决上面得问题,具体得看连接安全
- Guava缓存的使用
package com.mmall.common; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; public class TokenCache { public static final String TOKEN_PREFIX = "token_"; private static Logger logger = LoggerFactory.getLogger(TokenCache.class); private static LoadingCache<String, String> localCache = CacheBuilder.newBuilder() .initialCapacity(1000) .maximumSize(10000) //本地最大缓存10000 .expireAfterAccess(12, TimeUnit.HOURS) //缓存有效期 .build(new CacheLoader<String, String>() { //默认的数据加载实现,当调用get取值的时候,若是key没有对应的值,就调用这个方法进行加载 @Override public String load(String s) throws Exception { return "null"; } }); public static void setKey(String key, String value) { localCache.put(key, value); } public static String getKey(String key) { String value = null; try { value = localCache.get(key); if ("null".equals(key)) { return null; } return value; } catch (Exception e) { logger.error("localCache get error", e); } return null; } }
- Session的使用
Servlet的内置对象,具体查看Servlet九大内置对象架构
- 方法局部演进
功能模块
接口设计
门户_用户接口
####1.登陆并发
/user/login.do post(代码须要post方式请求),开放get,方便调试app
request
username,password
response
success
{ "status": 0, "data": { "id": 12, "username": "aaa", "email": "aaa@163.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 } }
####2.注册 /user/register.do
request
username,password,email,phone,question,answer
response
success
{ "status": 0, "msg": "校验成功" }
####3.检查用户名是否有效
/user/check_valid.do
/check_valid.do?str=admin&type=username就是检查用户名。
request
str,type str能够是用户名也能够是email。对应的type是username和email
response
success
{ "status": 0, "msg": "校验成功" }
####4.获取登陆用户信息 /user/get_user_info.do
request
无参数
response
success
{ "status": 0, "data": { "id": 12, "username": "aaa", "email": "aaa@163.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 } }
####5.忘记密码 /user/forget_get_question.do
localhost:8080/user/forget_get_question.do?username=geely
request
username
response
success
{ "status": 0, "data": "这里是问题" }
####6.提交问题答案 /user/forget_check_answer.do
localhost:8080/user/forget_check_answer.do?username=aaa&question=aa&answer=sss
request
username,question,answer
response
正确的返回值里面有一个token,修改密码的时候须要用这个。传递给下一个接口
success
{ "status": 0, "data": "531ef4b4-9663-4e6d-9a20-fb56367446a5" }
####7.忘记密码的重设密码 /user/forget_reset_password.do
localhost:8080/user/forget_reset_password.do?username=aaa&passwordNew=xxx&forgetToken=531ef4b4-9663-4e6d-9a20-fb56367446a5
request
username,passwordNew,forgetToken
response
success
{ "status": 0, "msg": "修改密码成功" }
####8.登陆中状态重置密码 /user/reset_password.do
request
passwordOld,passwordNew
response
success
{ "status": 0, "msg": "修改密码成功" }
####9.登陆状态更新我的信息 /user/update_information.do
request
email,phone,question,answer
response
success
{ "status": 0, "msg": "更新我的信息成功" }
####10.获取当前登陆用户的详细信息,并强制登陆 /user/get_information.do
request
无参数
response
success
{ "status": 0, "data": { "id": 1, "username": "admin", "password": "", "email": "admin@163.com", "phone": "13800138000", "question": "question", "answer": "answer", "role": 1, "createTime": 1478422605000, "updateTime": 1491305256000 } }
fail
{ "status": 10, "msg": "用户未登陆,没法获取当前用户信息,status=10,强制登陆" }
####11.退出登陆 /user/logout.do
request
无
response
success
{ "status": 0, "msg": "退出成功" }
后台_用户接口
####1.后台管理员登陆
/manage/user/login.do
request
String username, String password
response
success
{ "status": 0, "data": { "id": 12, "username": "aaa", "email": "aaa@163.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 } }
####2.用户列表
/manage/user/list.do
request
pageSize(default=10) pageNum(default=1)
response
success
{ "status": 0, "data": { "pageNum": 1, "pageSize": 3, "size": 3, "orderBy": null, "startRow": 1, "endRow": 3, "total": 16, "pages": 6, "list": [ { "id":17, "username":"rosen", "password":"", "email":"rosen1@happymmall.com", "phone":"15011111111", "question":"啊哈哈", "answer":"服不服", "role":0, "createTime":1489719093000, "updateTime":1513682138000 }, { "id":17, "username":"rosen", "password":"", "email":"rosen1@happymmall.com", "phone":"15011111111", "question":"啊哈哈", "answer":"服不服", "role":0, "createTime":1489719093000, "updateTime":1513682138000 } ], "firstPage": 1, "prePage": 0, "nextPage": 2, "lastPage": 6, "isFirstPage": true, "isLastPage": false, "hasPreviousPage": false, "hasNextPage": true, "navigatePages": 8, "navigatepageNums": [ 1, 2, 3, 4, 5, 6 ] } }