注册
注册流程
关键技术
1、查询该用户是否存在
通过userName去数据库中查询用户是否已存在
//1.检查数据库中是否已经存在该用户User dbuser = userMapper.selectByUserName(req.getUsername());if (dbuser != null) {throw new CaseServerException("用户名已存在", StatusCode.INTERNAL_ERROR);}
CaseServerException是自定义的一个异常类,它用来封装程序内部可判断出来的 Exception。StatusCode是一个枚举类,其中INTERNAL_ERROR是自定义的一个状态码
INTERNAL_ERROR(10400, "内部参数校验或逻辑出错"),
2、密码加密
加密分为多个步骤,首先生成盐,盐其实是一个 UUID:
String salt = CodecUtils.generateSalt();//CodecUtils的generateSalt()方法,public static String generateSalt(){return StringUtils.replace(UUID.randomUUID().toString(), "-", "");}
generateSalt 方法:UUID.randomUUID是用来生成一个唯一的 UUID,但 UUID 的标准格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)。因此需要用StringUtils.replace方法来将“-”替换成“”,使 UUID 中的 - 去掉
其次对用户密码进行一次 MD5 加密,接着将盐(UUID)拼接上加密后的密码。最后对拼接后的字符串再进行一次 MD5 加密。
public static String md5Hex(String data,String salt) {if (StringUtils.isBlank(salt)) {salt = data.hashCode() + "";}return DigestUtils.md5Hex(salt + DigestUtils.md5Hex(data));}
MD5 和 md5Hex 的区别:
- MD5 是单向加密,不可逆、不能解密的,而 md5Hex 是可逆的,可以加密也可以解密
MD5 是16位以 16 个元素的形式返回值,而 md5hex 是以32位16进制的小写字符串形式返回值
3、保存
在对密码进行加密后,将用户名、密码、盐等信息保存到数据库,并设置初始化的权限等。保存盐是为了登录时做校验的工作。
4、set cookie
用户注册后需要自动登录,并将登录状态保存。设置 Cookie 的值,并使其在指定时间内生效
CookieUtils.setCookie(request, response, "username", req.getUsername(),60 * 60 * 24, null, false);
"username":cookieNamereq.getUsername():cookieValue60 * 60 * 24:cookieMaxAge // cookie 生效的最大秒数null:encodeStringfalse:httpOnly // 是否开启 httpOnly登录
登录流程
关键技术
1、校验密码是否正确
密码校验的过程和注册有点类似:
先从数据库中获取用户的盐A、密码B(加密后的)
- 然后对用户输入的密码进行一次 MD5 加密,加密后得到 C
- 随后拼接 A+C,再对 A + C 做一次 MD5 加密,得到 D
最后校验 B 是否等于 D
if (!dbuser.getPassword().equals(CodecUtils.md5Hex(req.getPassword(),dbuser.getSalt()))) {throw new CaseServerException("密码错误",StatusCode.INTERNAL_ERROR);}
2、set cookie
3、权限刷新
首先在
application.properties获取权限开关authority.flag的值,判断是否开启了权限。默认是 false 的关闭状态@Value("${authority.flag}")private Boolean authorityFlag;
开启权限开关情况下,去获取用户的
authorityName(权限名称)。但用户注册时默认保存了一个空的权限名称,假如没有被修改过,那用户就会是空权限。因此当用户权限仍是空的情况下,会给用户配置默认权限名称DEFAULT_AUTHORITY_NAME,DEFAULT_AUTHORITY_NAME = “ROLE_USER”,普通用户权限if (authorityFlag) {String authorityName = dbuser.getAuthorityName();if (StringUtils.isEmpty(authorityName)) {authorityName = SystemConstant.DEFAULT_AUTHORITY_NAME;}}
最后在数据库中查询该权限名称对应有哪些权限,并给用户设置权限
if (authorityFlag) {String authorityName = dbuser.getAuthorityName();if (StringUtils.isEmpty(authorityName)) {authorityName = SystemConstant.DEFAULT_AUTHORITY_NAME;}Authority authority = authorityMapper.selectByAuthorityName(authorityName);if (Objects.nonNull(authority)) {String[] authorityContentArray = authority.getAuthorityContent().split(SystemConstant.COMMA);roleAuthority.put(authority.getAuthorityName(), Arrays.asList(authorityContentArray));LOGGER.info("刷新权限信息,authorityName: {}", authorityName);}}
注:这里的权限是指测试用例查看的权限
目前系统中有3种权限名称,分别是:ROLE_USER:普通用户
- ROLE_ADMIN:管理员
- ROLE_SA:超级管理员
退出登录
退出登录时,会删除 cookie 中的 username 和 jsessionid
