微服务之用户注册与登录
用户注册逻辑:用户注册账号,输入姓名邮箱等信息注册后,后端就会发送邮件给用户邮箱。邮箱收到一个url,这个url信息中包含了用户名和uuid,点击后,也就是访问了激活的后端代码,后端将user表中的is_verfiy字段改成Y,完成验证 。登陆的时候仅允许注册并激活的用户登陆。注册时获取图片验证码的代码CaptchaController:package com.cskaoyan.gateway.c
用户注册逻辑:用户注册账号,输入姓名邮箱等信息注册后,后端就会发送邮件给用户邮箱。邮箱收到一个url,这个url信息中包含了用户名和uuid,点击后,也就是访问了激活的后端代码,后端将user表中的is_verfiy字段改成Y,完成验证 。
登陆的时候仅允许注册并激活的用户登陆。
注册时获取图片验证码的代码
CaptchaController:
package com.cskaoyan.gateway.controller.user;
/**
* create by ciggar on 2020/04/05
*/
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.commons.tool.utils.CookieUtil;
import com.mall.user.IKaptchaService;
import com.mall.user.annotation.Anoymous;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dto.KaptchaCodeRequest;
import com.mall.user.dto.KaptchaCodeResponse;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/user")
public class CaptchaController {
@Reference(timeout = 3000, check = false)
IKaptchaService kaptchaService;
/**
* 获取验证码
*/
@Anoymous
@GetMapping("/kaptcha")
public ResponseData getKaptchaCode(HttpServletResponse response) {
KaptchaCodeRequest kaptchaCodeRequest = new KaptchaCodeRequest();
// 获取图片验证码
KaptchaCodeResponse kaptchaCodeResponse = kaptchaService.getKaptchaCode(kaptchaCodeRequest);
if (kaptchaCodeResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())) {
// 生成一个cookie key:kaptcha_uuid,value:uuid
Cookie cookie = CookieUtil.genCookie("kaptcha_uuid", kaptchaCodeResponse.getUuid(), "/", 60);
cookie.setHttpOnly(true);
response.addCookie(cookie);
return new ResponseUtil<>().setData(kaptchaCodeResponse.getImageCode());
}
return new ResponseUtil<>().setErrorMsg(kaptchaCodeResponse.getCode());
}
@Anoymous
@PostMapping("/kaptcha")
public ResponseData validKaptchaCode(@RequestBody String code, HttpServletRequest httpServletRequest) {
KaptchaCodeRequest request = new KaptchaCodeRequest();
String uuid = CookieUtil.getCookieValue(httpServletRequest, "kaptcha_uuid");
request.setUuid(uuid);
request.setCode(code);
// 校验验证码
// 通过uuid去获取验证码,和我们传过去的验证码对比,如果一致,验证成功,否则验证失败。
KaptchaCodeResponse response = kaptchaService.validateKaptchaCode(request);
if (response.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())) {
return new ResponseUtil<>().setData(null);
}
return new ResponseUtil<>().setErrorMsg(response.getCode());
}
}
KaptchaServiceImpl:
package com.mall.user.services;
import com.mall.user.IKaptchaService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dal.entitys.ImageResult;
import com.mall.user.dto.KaptchaCodeRequest;
import com.mall.user.dto.KaptchaCodeResponse;
import com.mall.user.utils.ExceptionProcessorUtils;
import com.mall.user.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* ciggar
* create-date: 2019/8/6-14:45
*/
@Slf4j
@Component
@Service
public class KaptchaServiceImpl implements IKaptchaService {
@Autowired
RedissonClient redissonClient;
private final String KAPTCHA_UUID = "kaptcha_uuid";
@Override
public KaptchaCodeResponse getKaptchaCode(KaptchaCodeRequest request) {
KaptchaCodeResponse response = new KaptchaCodeResponse();
try {
// 生成带验证码的图片,调用的一些Java和图形相关的API
ImageResult capText = VerifyCodeUtils.VerifyCode(140, 43, 4);
String uuid = UUID.randomUUID().toString();
// 把k-v放入redis中,k:KAPTCHA_UUID+uuid,v:capText.getCode()
RBucket rBucket = redissonClient.getBucket(KAPTCHA_UUID + uuid);
rBucket.set(capText.getCode());
log.info("产生的验证码:{},uuid:{}", capText.getCode(), uuid);
// 设置过期时间
rBucket.expire(120, TimeUnit.SECONDS);
// 把验证码图片对象返回
response.setImageCode(capText.getImg());
response.setUuid(uuid);
response.setCode(SysRetCodeConstants.SUCCESS.getCode());
response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
} catch (Exception e) {
log.error("KaptchaServiceImpl.getKaptchaCode occur Exception :" + e);
ExceptionProcessorUtils.wrapperHandlerException(response, e);
}
return response;
}
@Override
public KaptchaCodeResponse validateKaptchaCode(KaptchaCodeRequest request) {
KaptchaCodeResponse response = new KaptchaCodeResponse();
try {
request.requestCheck();
String redisKey = KAPTCHA_UUID + request.getUuid();
RBucket<String> rBucket = redissonClient.getBucket(redisKey);
String code = rBucket.get();
log.info("请求的redisKey={},请求的code={},从redis获得的code={}", redisKey, request.getCode(), code);
if (StringUtils.isNotBlank(code) && request.getCode().equalsIgnoreCase(code)) {
response.setCode(SysRetCodeConstants.SUCCESS.getCode());
response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
return response;
}
response.setCode(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getCode());
response.setMsg(SysRetCodeConstants.KAPTCHA_CODE_ERROR.getMessage());
} catch (Exception e) {
log.error("KaptchaServiceImpl.validateKaptchaCode occur Exception :" + e);
ExceptionProcessorUtils.wrapperHandlerException(response, e);
}
return response;
}
}
- 对称加密:
A给B传输数据m,在传输的过程中+e(加密),B收到了数据c后,-e(解密),获得数据m。
加密操作可能更复杂,如m*e+s。
- 非对称加密:
A把传输数据给B,B首先生成两个具有相关新的数字e(公钥)和d(私钥)。
B把e传给A(以公开的方式), A通过e公钥的某个算法(例如+e)得到一个c(密文),并把c传给B(以公开的方式)。
A收到密文c后,通过密文求解原文的过程不是-e,而是-d(私钥),解得m(明文)。
也就是说加密时用e(公钥)进行加密,解密时用d(私钥)进行解密。
就算你知道e(公钥)和c(密文),你也不知道私钥,无法解密而获得m(明文)。
- 下面来介绍一种最典型的非对称加密方式:RSA加密算法
- 要求B找出两个质数p、q。
- n = p * q
- f(n) = (p - 1) * (q - 1) (欧拉函数)
- 找出公钥e,1 < e < f(n) 且 e和f(n)互斥,在这个条件内随便找一个整数即可。
找出私钥d,使得e*d/f(n)后的余数为1。
传输的数据是m
加密:m^e / n 求余数c
解密:c^d / n 求余数m(可以证明这个余数一定是m)。
这种算法的安全性如何呢?
传输中可能被截取的数据有:n、e、c
解密需要的数据:n、d、c
黑客要想解密就得根据e求出d,已知公式:e*d/f(n)后的余数为1。所以得知道f(n),要知道f(n)就得先知道p、q,要知道p、q就得对n进行质因数分解。
大数的质因数分解是很困难的。
RSA算法常用的n是1024位的二进制数,目前想分解这么大的数,普通计算机需要计算十年,量子计算机需要计算七天,所以银行系统都会定期进行更新。
更多推荐
所有评论(0)