Java后端如何保证⽤户注册登录接⼝的安全性之⽤户登录篇 下⾯废话也不多说,直接上代码,当然了,还是⽼规矩,只分享service层的代码来陈述具体的思路,⾄于全套代码⽆法提供(还请谅解)。另外代码中的注释已经有⾜够多的解释,千万别忘了他们。
package sy.service.impl;
ParseException;
SimpleDateFormat;
import java.util.Calendar;
入队申请书一年级import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apachemons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import DateUtil;
import bile.MobileUtil;
@Service("userService")
public class UserServiceImpl implements UserService {
private static final Logger logger = Logger(UserServiceImpl.class);
/**
登录时,当⽤户输⼊⼿机号后,就调⽤该接⼝判断当前⼿机号是否注册,
如果是已经注册过的,后台就会⽣成rsa公私钥对并将公钥返回给前端;
如果没有注册,就提醒⽤户当前⼿机号未注册,以此来提⾼⽤户体验
*/
@Override
public Result findUser(String mobile, HttpServletRequest request) {
Result result = new Result();
// 判断传⼊的⼿机号格式是否正确
if (StringUtils.isBlank(mobile)) {
result.setSuccess(false);
result.setMsg("缺少必要参数");
return result;
}
mobile = im();
// 判断传⼊的⼿机号格式是否正确
if (mobile.length() != 11 || !MobileUtil.isMobileNum(mobile)) {
result.setSuccess(false);
result.setMsg("传⼊的⼿机号格式不正确");
return result;
}
//查询当前⼿机号是否注册,此处省略具体的数据库相关的操作
if(未注册){//伪代码,实际使⽤需换成你⾃⼰的dao层查询
result.setSuccess(false);
result.setMsg("当前⼿机号没有注册");
result.setMsg("当前⼿机号没有注册");
return result;
}
String rsaPublicKey = "login_rsa_public_" + mobile;
String rsaPrivateKey = "login_rsa_private_" + mobile;
Long rsa = l(rsaPublicKey);
if (rsa > 60 *15+5) {// 原来的公钥有效时间⼤于15分钟,继续使⽤
result.(rsaPublicKey));//该字段保存⽣成的rsa公钥并返回给前端
} else {
Map<Integer, String> map = KeyPair();
if (map != null && (0) != null) {
RedisUtils.set(rsaPublicKey, (0), 60 * 120 + 120);// 保存公钥
RedisUtils.set(rsaPrivateKey, (1), 60 * 120 + 150);// 保存私钥,2⼩时有效
result.(0));
}
}
// 登录失败超过三次就要输⼊验证码,判断当前⽤户是否需要设置验证码
String times = ( mobile + "_login_error_times");
if (times != null && new Integer(times).intValue() >= 3) {
result.setPage(1);//告诉前端,此次请求需要输⼊⾕歌图形验证码;此时公钥其实已经⼀并返回给前端,
//如果前端没有携带⾕歌图形验证码就直接调⽤登录接⼝,请求依旧会失败,因为登录接⼝有做检验,有判断当前⽤户今⽇登录次数是否超次数 }
result.setSuccess(true);
return result;
}
/**
⽤户登录接⼝service层的代码,按照惯例,controller层就不贴出来了
mobile是登录的⼿机号,pwd是使⽤rsa公钥加密后的密码,code是⾕歌图形验证码
*/
@Override
public Result login(String mobile,String pwd,String code, HttpServletRequest request) {
Result result = new Result();
// 判断请求参数是否正确
if (StringUtils.isBlank(mobile) || StringUtils.isBlank(pwd)) {
result.setSuccess(false);
result.setMsg("缺少必要的参数");
return result;
电信积分兑换}
mobile = im();
// 判断传⼊的⼿机号格式是否正确
if (mobile.length() != 11 || !MobileUtil.isMobileNum(mobile)) {
result.setSuccess(false);
result.setMsg("传⼊的⼿机号格式不正确");
return result;
}
// 判断是否有图⽚验证码
String kaptcha = ("login_captcha_" + mobile);
if (kaptcha != null && code != null && !LowerCase().equals(kaptcha)) {
result.setPage(1);
result.setSuccess(false);
result.setMsg("您输⼊的验证码有误,请重新输⼊");
return result;
}
String rsaPublicKey = "login_rsa_public_" + mobile;
String rsaPrivateKey = "login_rsa_private_" + mobile;
// 从redis数据库获取私钥
String privateKey = (rsaPrivateKey);
if (StringUtils.isBlank(privateKey)) {
RedisUtils.del(rsaPublicKey);
RedisUtils.del(rsaPrivateKey);
result.setPage(1);
result.setSuccess(false);
result.setMsg("密钥验证失败,请输⼊新的验证码后再登录");
result.setStatus("1");
return result;
}
刘涛演过什么电视剧// 判断当前⼿机号的登录失败次数,防⽌有⼈暴⼒破解⽤户的密码
String limitKey = mobile + "_login_error_times";
String limitTimes = (limitKey);
Integer times = 1;
if (limitTimes != null) {
if (new Integer(limitTimes).intValue() >= 6) {
result.setSuccess(false);
result.setMsg("当前账号今⽇登录失败次数超过6次,为保证您的账号安全,系统已锁定当前账号,您可明天再登录或⽴即重置密码后使⽤新密码登录!"); return result;
}
times = new Integer(limitTimes) + 1;
if (kaptcha == null && times > 3) {
result.setPage(1);//该字段如果为1,表⽰前端需要⽤户输⼊⾕歌图形验证码接⼝
result.setSuccess(false);
result.setMsg("您没有输⼊验证码");
return result;
}
}
// 使⽤私钥解密后的密码
pwd = RSAEncrypt.decrypt(pwd, privateKey);
if (pwd == null) {
result.setSuccess(false);
result.setMsg("解密失败,您传⼊的数据有误");
result.setStatus("1");
return result;
}
//核⼼业务隐⾝符,此处通过⼿机号获取⽤户的密码,然后通过对应的加密⽅式来检验密码是否⼀致性
if(密码不正确){//伪代码
// 记录密码输⼊错误数
RedisUtils.set(limitKey, times + "", TodaySurplusTime());
if (times > 2) {
result.setPage(1);// 密码输错两次,就需要输⼊⾕歌图形验证码
}
result.setSuccess(false);
result.setMsg("登录密码错误");
return result;
}
//密码登录成功,执⾏登录成功后的核⼼业务,此处省略
// 删除登录失败次数的标识
if (limitTimes != null) {
RedisUtils.del(limitKey);
}
// 删除验证码
// 删除验证码
if (kaptcha != null) {
RedisUtils.del("login_captcha_" + mobile);
}
// 删除保存的公钥私钥
RedisUtils.del(rsaPublicKey);
RedisUtils.del(rsaPrivateKey);
result.setSuccess(true);
return result;
}
/**
获取⽤户重置登录密码所需要的⼿机短信验证码的接⼝
mobile是⼿机号,contents是⾕歌图形验证码(该值可能为null)
*/
@Override
public Result sendMobileCode(String mobile, String contents, HttpServletRequest request) {
办公管理制度Result result = new Result();
if (StringUtils.isBlank(mobile)) {
result.setSuccess(false);
result.setMsg("请求参数不全");
return result;
}
mobile = im();
/
/ 判断传⼊的⼿机号格式是否正确
if (mobile.length() != 11 || !MobileUtil.isMobile(mobile)) {
result.setSuccess(false);
result.setMsg("传⼊的⼿机号格式不正确");
return result;
}
//业务代码隐⾝符1,此处需要⽤该⼿机号去查询当前帐号是否注册,只有注册的号码才能调⽤重置密码的⼿机短信验证码 if(⼿机号未注册){
result.setSuccess(false);
result.setMsg("当前⼿机号未注册,请先注册");
return result;
}
String kapchatKey = "kaptcha_reset_login_" + mobile;//记录此次的⾕歌图形验证码,如果有的话
String mobileKey = "mobile_reset_login_" + mobile;//记录此次的重置登录密码的⼿机短信验证码
String todayKey = "mobile_code_times_" + mobile;//记录今⽇验证码的次数
// 验证码⼗分钟内有效,2分钟后才能重新发送
Long times = l(mobileKey);
if (times > 60 * 18) {
result.setSuccess(false);
result.setMsg("距离您上次发送验证码不⾜两分钟,请两分钟后再尝试获取");
return result;
}
// 判断当前⼿机号今天发送密码次数是否已达上线,每天9条,具体条数根据⾃⼰的需求制定
String todayTimes = (todayKey);
int todayCount = 1;
if (todayTimes != null) {
todayCount = new Integer(todayTimes);
if (todayCount >= 9) {
result.setSuccess(false);
result.setMsg("当前⼿机号今⽇发送验证码已达上限,请明⽇再来");
return result;
}
todayCount++;
}
/
/今天调⽤接⼝超过三次,就需要调⾕歌图形验证码,这也是对短信接⼝的⼀种保护机制
if(todayCount>3){
result.setPage(1);//只要今⽇获取验证码次数超过三次,之后每次调⽤短信验证码接⼝时都要先调⽤⾕歌验证码
if(StringUtils.isBlank(contents)){
result.setSuccess(false);
result.setMsg("为保证您账号安全,请输⼊图形验证码获取⼿机短信");
return result;
}
// 检验图形验证码
String kapchat = (kapchatKey);
if (kapchat == null) {
result.setMsg("图形验证码已失效,请重新输⼊");
result.setSuccess(false);九制陈皮
return result;
} else if (!kapchat.LowerCase())) {
result.setSuccess(false);
result.setMsg("您输⼊的验证码错误,请重新输⼊");
return result;
}
}else if(todayCount==3){
result.setPage(1);
}
String msg = null;
2014年母亲节是哪一天Map<Integer, String> map = null;
String publicKey = null;
String rsaPublicKey = "rsa_public_reset_login_" + mobile;// redis保存的公钥的key
String rsaPrivateKey = "rsa_private_reset_login_" + mobile;// redis中保存私钥的key
try {
//判断原来的公钥是否可以使⽤,如果可以,就不需要重新⽣成新的rsa公钥私钥对
Long rsa = l(rsaPublicKey);
if (rsa > 60 * 20 + 10) {// 原来的公钥有效时间⼤于20分钟,继续使⽤
publicKey = (rsaPublicKey);
} else {
/
/ ⽣成公钥和私钥
map = KeyPair();
if (map == null || (0) == null) {
result.setSuccess(false);
result.setMsg("⽣成公钥私钥失败,请联系管理员");
return result;
}
}
// 要发送的验证码
String code = (int) ((Math.random() * 9 + 1) * 100000) + "";
// 业务代码隐⾝符2,此处省略调⽤第三⽅接⼝给⽤户⼿机发送验证码的操作
if(短信发送成功){
result.setSuccess(true);
result.setMsg("您的⼿机验证码发送成功,请注意查收,本验证码20分钟内有效");
// 保存私钥,返回公钥
if (map != null) {
RedisUtils.set(rsaPublicKey, (0), 60 * 90 + 250);// 2⼩时有效
RedisUtils.set(rsaPrivateKey, (1), 60 * 90 + 300);// 2⼩时有效
result.(0));
}
if (publicKey != null) {
result.setStatus(publicKey);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论